How do I avoid undefined method `empty?' for nil:NilClass? - ruby-on-rails

I'm running into an error. undefined method empty? for nil:NilClass? It seems to happen part of the time. I put the same controller code in show and new. Can someone point me in the right direction as to why I'm getting the error and how can this be avoided? I'm creating customers and attaching a list to them. Sometimes the list exists before the customer sometimes not. Thanks
Setup is Lists has many customers. So I'm going to customers_path and clicking new_customer_path and I get the error. If I make a list first sometimes it works. Sometimes If I refresh things work. If I reboot the server then it fails on first attempt. So I know something is working but I'm not sure why I get inconsistent results? Thoughts
customer_controller.rb - index - Trying to maybe pre set it?
#customer = Customer.new
#customers = Customer.where("user_id = ?", uid).order(updated_at: :desc)
# #lists = List.where(user_id: current_user.id).order("created_at asc").pluck(:name, :id)
#lists = List.where(user_id: current_user.id).order("created_at asc")
customer_controller.rb - new
def new
#customer = Customer.new
puts " "
puts "============="
# #lists = List.where(user_id: current_user.id).order("created_at asc").pluck(:name, :id) rescue nil
#lists = List.where(user_id: current_user.id).order("created_at asc")
puts #lists.count
puts " "
puts "============="
end
customers_form.erb which is _form.erb
<%= form_for(customer) do |f| %>
<% if customer.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(customer.errors.count, "error") %>
prohibited this customer from being saved:</h2>
<ul>
<% ccustomer.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="form-box">
<div class="field">
<%= f.label "First Name" %>
<%= f.text_field :firstname, :class => 'form-control' %>
</div>
<div class="field center">
<label>List</label>
<%#= f.select :list_id, options_for_select(#lists.map{ |list| [list.name, list.id] }), prompt: 'Not Assigned', class: 'form-control input-lg' %>
<%= f.select :list_id, #lists, { :include_blank => 'Not Assigned'}, class: 'form-control input-lg' %>
</div>
<%= f.hidden_field :user_id, :value => current_user.id %>
<br>
<div class="actions">
<%= f.submit "Save", :class => "btn btn-lg btn-long btn-warning" %>
</div>
</div>
My log output:
Started GET "/customers/new" for 127.0.0.1 at 2020-03-01 20:37:41 -0800
Processing by CustomersController#new as HTML
User Load (1.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2 [["id", 18], ["LIMIT", 1]]
Rendering customers/new.html.erb within layouts/application
Rendered customers/_form.html.erb (29.6ms)
Rendered customers/new.html.erb within layouts/application (32.3ms)
Completed 500 Internal Server Error in 74ms (ActiveRecord: 11.3ms)
ActionView::Template::Error (undefined method `empty?' for nil:NilClass):
39:
40: <div class="field center">
41: <label>List</label>
42: <%= f.select :list_id, #lists, { :include_blank => 'Not Assigned'}, class: 'form-control input-lg' %>
43: </div>
44: <% end %>
45:
app/views/customers/_form.html.erb:42:in `block in _app_views_customers__form_html_erb__810149171042607559_70218705879220'
app/views/customers/_form.html.erb:1:in `_app_views_customers__form_html_erb__810149171042607559_70218705879220'
app/views/customers/new.html.erb:8:in `_app_views_customers_new_html_erb__187385255323143294_70218705803580'
Rendering /Users/MyName/.rvm/gems/ruby-2.5.1/gems/actionpack-5.0.7/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb within rescues/layout
Rendering /Users/MyName/.rvm/gems/ruby-2.5.1/gems/actionpack-5.0.7/lib/action_dispatch/middleware/templates/rescues/_source.html.erb
Rendered /Users/MyName/.rvm/gems/ruby-2.5.1/gems/actionpack-5.0.7/lib/action_dispatch/middleware/templates/rescues/_source.html.erb (4.0ms)
Rendering /Users/MyName/.rvm/gems/ruby-2.5.1/gems/actionpack-5.0.7/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb
Rendered /Users/MyName/.rvm/gems/ruby-2.5.1/gems/actionpack-5.0.7/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb (1.6ms)
Rendering /Users/MyName/.rvm/gems/ruby-2.5.1/gems/actionpack-5.0.7/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb
Rendered /Users/MyName/.rvm/gems/ruby-2.5.1/gems/actionpack-5.0.7/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb (0.7ms)
Rendered /Users/MyName/.rvm/gems/ruby-2.5.1/gems/actionpack-5.0.7/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb within rescues/layout (69.2ms)

Try this, remove pluck from here
#lists = List.where(user_id: current_user.id).order("created_at asc")
map here instead
<%= f.select :list_id, options_for_select(#lists.map{ |list| [list.name, list.id] }), prompt: 'Not Assigned', class: 'form-control input-lg' %>
Give it a try!

A better approach is to start using rescue , below is just a small snippet how to do it -
def index
begin
#lists = List.where(user_id: current_user.id)
rescue
flash[:notice] = "ERROR"
redirect_to(:action => 'index')
return
end
flash[:notice] = "OK"
redirect_to(:action => 'index')
end
This also works -
#lists = List.where(user_id: current_user.id).order("created_at asc").pluck(:name, :id) rescue nil
Read more about it here - https://guides.rubyonrails.org/debugging_rails_applications.html#catching-exceptions

Related

ActionController::UnknownFormat with js

Im new at ruby and I try to add ajax for my controller, but I`m probably missing something
My controller
class StocksController < ApplicationController
def search
if params[:stock].present?
#stock = Stock.new_lookup(params[:stock])
if #stock
respond_to do |format|
format.js {render partial: 'users/result'}
end
else
flash[:alert] = "Please enter a valid symbol to search"
redirect_to my_portfolio_path
end
else
flash[:alert] = "Please enter a symbol to search"
redirect_to my_portfolio_path
end
end
end
My view. When I`m not writing 'turbo:false' nothing happens
<div class="search-area">
<h3>Search Stocks</h3>
<%= form_tag search_stock_path, data: {turbo: false}, method: :get do %>
<div class="form-group row">
<div class="col-sm-9 no-right-padding">
<%= text_field_tag :stock, params[:stock], placeholder: "Stock ticker symbol", autofocus: true, class: "form-control form-control-large"%>
</div>
<div class="col-sm-3 no-left-padding">
<%= button_tag type: :submit, class: "btn btn-success" do %>
<%= fa_icon 'search 1.5x' %>
<% end %>
</div>
</div>
<% end %>
</div>
My terminal:
Started GET "/search_stock?stock=MSFT&button=" for 127.0.0.1 at 2023-01-27 22:44:35 +0200
Processing by StocksController#search as HTML
Parameters: {"stock"=>"MSFT", "button"=>""}
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT ? [["id", 1], ["LIMIT", 1]]
Completed 406 Not Acceptable in 1701ms (ActiveRecord: 1.2ms | Allocations: 8322)
ActionController::UnknownFormat (ActionController::UnknownFormat):
app/controllers/stocks_controller.rb:6:in `search'
Error image
I found articles with a similar error, but there was no answer
In the terminal I see that but dont know what to do
Processing by StocksController#search as HTML

Passing an ID through a hidden form field

I tried to do something similar to this in a form, but get this error:
Started POST "/opinions" for 127.0.0.1 at 2019-01-03 17:11:12 -0800
Processing by OpinionsController#create as JS
Parameters: {"utf8"=>"✓", "opinion"=>{"content"=>"This is an opinion"}, "type_of"=>"pro", "topicId"=>"{:value=>2}", "commit"=>"Create Opinion"}
User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
Topic Load (0.0ms) SELECT "topics".* FROM "topics" WHERE "topics"."id" = ? LIMIT ? [["id", nil], ["LIMIT", 1]]
Completed 404 Not Found in 3ms (ActiveRecord: 0.0ms)
ActiveRecord::RecordNotFound (Couldn't find Topic with 'id'=):
app/controllers/opinions_controller.rb:6:in `create'
opinions_form.html.erb:
<%= form_for(opinion, :html=> {class:"form-horizontal", role:"form"}, remote: true) do |f| %>
<div class="form-group">
<div class="col-sm-12">
<%= f.text_area :content, rows:4, class: "form-control", placeholder: "Opinion" %>
</div>
</div>
<%= hidden_field_tag 'type_of', typeOf %>
<%= hidden_field_tag :topicId, :value => #topic.id %>
<% puts "ID: " + #topic.id.to_s %>
<div class="form-group">
<div class="col-sm-12">
<%= f.submit %>
</div>
</div>
<% end %>
Relevant code in controller:
def create
#opinion = Opinion.new(opinion_params)
#opinion.user = current_user
#opinion.topic = Topic.find(params[:opinion][:topicId])
if #opinion.save
flash[:success] = 'Opinion Added'
else
puts #opinion.errors.full_messages
flash[:danger] = 'Opinion not Added'
end
end
private
def opinion_params
params.require(:opinion).permit(:content, :type_of)
end
and finally, relevant code in the topic show page:
<td>
<%= render 'opinions/form', opinion: Opinion.new, typeOf: "pro", :topic => #topic %>
</td>
<td>
<%= render 'opinions/form', opinion: Opinion.new, typeOf: "con", :topic => #topic %>
</td>
As you can see in the request parameters:
Parameters: {"utf8"=>"✓", "opinion"=>{"content"=>"This is an opinion"}, "type_of"=>"pro", "topicId"=>"{:value=>2}", "commit"=>"Create Opinion"}
The topicId parameter is not nested under opinion, so you need to change your finder to:
#opinion.topic = Topic.find(params[:topicId][:value])
You can also remove the superfluous value key in your view:
<%= hidden_field_tag :topicId, #topic.id %>
Which would further simplify your finder:
#opinion.topic = Topic.find(params[:topicId])
As an aside. Note that idiomatic ruby calls for snake_case in all identifiers. This won't change how your code works, but it will help other Ruby developers read your code.

Rails: ForbiddenAttributesError for dynamic simple form

I followed the answer given here to create a simple dynamic form (not nested). The idea is to invite several people with their email. Then I have an "Add Team Member" button to add the fields to enter the coworker email.
I get the following error but I don't know why:
ActiveModel::ForbiddenAttributesError in InvitationsController#create
The parameters:
{"utf8"=>"✓",
"authenticity_token"=>"zLs8DWkzO+bPc2jGhFptgc+BAGAwzr1kcn/hkX/6vQbQ/cDCzuqoGCMGUTcYHs+up7nBzHFiEXVcKustyL1KIA==",
"invitation"=>[{"email"=>"test#test.fr", "_destroy"=>"false", "user_id"=>"1"}, {"email"=>"test2#test2.fr", "_destroy"=>"false", "user_id"=>"1"}],
"commit"=>"Save Team Members"}
My create action and invitation_params in the controller:
def create
puts params[:invitation].to_yaml
params[:invitation].each do |invitation_params|
Invitation.create(invitation_params)
end
redirect_to invitation_path
end
def invitation_params
params.require(:invitation).permit(:id, :email, :user_id, :_destroy, :token)
end
My form:
<%= form_for(invitation) do |f| %>
<% if invitation.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(invitation.errors.count, "error") %> prohibited this invitation from being saved:</h2>
<ul>
<% invitation.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div id="container_invitations"></div>
<%= link_to "Add a New Team Member", add_invitation_path, :method => :post, :remote => true %>
<div class="actions">
<%= f.submit "Save Team Members", class: "cta2" %>
</div>
<% end %>
add_invitation controller action (to add the fields dynamically):
def add_invitation
respond_to do |format|
format.js
end
end
add_invitation.js.erb:
$('#container_invitations').append("<%= escape_javascript(render :partial => 'invitation_fields_render') %>");
$('.remove_fields').on('click', function(e) {
$(this).parent().remove();
});
_invitation_fields_render.html.erb (the partial with the fields)
<div class="new_invitation_row">
<%= email_field_tag "invitation[][email]", nil, placeholder: "Team Member Email", :required => 'required' %>
<%= hidden_field_tag "invitation[][_destroy]", nil, value: false %>
<a class="remove-link remove_fields dynamic" href="#"><i class="fa fa-trash fa-lg" title="Remove"></i></a>
<%= hidden_field_tag "invitation[][user_id]", nil, value: current_user.id %>
</div>
My invitation model:
class Invitation < ActiveRecord::Base
has_secure_token
belongs_to :user
end
Thank you.
UPDATE
I added the new params.permit line proposed by IngoAlbers. I still get the error. Here is the full stacktrace of the error:
Started POST "/invitations" for 127.0.0.1 at 2017-12-01 07:49:02 +0000
Processing by InvitationsController#create as HTML Parameters:
{"utf8"=>"✓",
"authenticity_token"=>"pV5wQj3QHXksNEtJ8nZSjWDc8VyHiewVCt4A1+ijH8G5GIyNmgmOh8BBcrhuMvCiCOQw8MYlQAQkiwprX+To5w==",
"invitation"=>[{"email"=>"test#test.fr", "_destroy"=>"false",
"user_id"=>"1"}], "commit"=>"Save Team Members"} User Load (0.4ms)
SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY
"users"."id" ASC LIMIT ? [["id", 1], ["LIMIT", 1]] CoreBot Load
(0.2ms) SELECT "core_bots".* FROM "core_bots" WHERE "core_bots"."id"
= ? LIMIT ? [["id", 1], ["LIMIT", 1]] Completed 500 Internal Server Error in 4ms (ActiveRecord: 0.6ms)
ActiveModel::ForbiddenAttributesError
(ActiveModel::ForbiddenAttributesError):
app/controllers/invitations_controller.rb:35:in block in create'
app/controllers/invitations_controller.rb:34:ineach'
app/controllers/invitations_controller.rb:34:in `create' Rendering
/Users/nicolasleroux/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/actionpack-5.0.6/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb
within rescues/layout Rendering
/Users/nicolasleroux/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/actionpack-5.0.6/lib/action_dispatch/middleware/templates/rescues/_source.html.erb
Rendered
/Users/nicolasleroux/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/actionpack-5.0.6/lib/action_dispatch/middleware/templates/rescues/_source.html.erb
(5.3ms) Rendering
/Users/nicolasleroux/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/actionpack-5.0.6/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb Rendered
/Users/nicolasleroux/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/actionpack-5.0.6/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb (2.5ms) Rendering
/Users/nicolasleroux/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/actionpack-5.0.6/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb
Rendered
/Users/nicolasleroux/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/actionpack-5.0.6/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb
(1.5ms) Rendered
/Users/nicolasleroux/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/actionpack-5.0.6/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb
within rescues/layout (93.1ms)
The problem is that invitation is an array. So you actually need to permit the array in the invitation_params.
def invitation_params
params.permit(invitation: [:id, :email, :user_id, :_destroy, :token])
end
In addition you have a problem in the create action itself.
You don't actually use the permitted parameters, that was defined.
It should probably look like this:
def create
invitation_params[:invitation].each do |invitation|
Invitation.create(invitation)
end
redirect_to invitation_path
end

Rails ActionController::ParameterMissing error

I want to update the status field on a form independently of the form itself. In other words, the user can change the status via a pop up. Once they hit submit, the window with the form closes. I have a similar situation that works but can't duplicate it here.
I am calling the popup with.
<%= link_to( '<button>Change the status</button>'.html_safe,
"/complaints/edit_status",
'data-popup' => true,
remote: true,
:class => "button_class",
:onclick=>"window.open(this.href,'change the status', 'height=500, width=500');
return false;"
) %><br>
my applicable routes are
get 'complaints/edit_status' => 'complaints#edit_status'
post 'complaints/edit_status' => 'complaints#edit_status'
The edit_status method in my controller is
def edit_status
#complaint = Complaint.find($current_record_id)
respond_to do |format|
if #complaint.update_attributes(complaint_params)
format.html { render :text => '<script type="text/javascript">
alert("The status was updated");
window.close();
</script>' }
else # otherwise show a standard message
format.html { render :text => '<script type="text/javascript">
alert(" There was an error in saving");
window.close();
</script>'
}
end
end
end
my edit_status.html.erb is simply <%= render 'form_for_status' %>
My complaints form is
<%= form_for #complaint, :html => { :class => 'form-horizontal', multipart: true} do |f| %>
<% if #complaint.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#complaint.errors.count, "error") %> prohibited this complaint from being saved:</h2>
<ul>
<% #complaint.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field" id="refresh_status">
<%= f.label :status %><br>
<%= f.select :status, options_for_status, :prompt => 'Select One' %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
The error I am getting is
ActionController::ParameterMissing in ComplaintsController#edit_status
param is missing or the value is empty: complaint
Rails.root: C:/Users/cmendla/RubymineProjects/internal_complaints
Application Trace | Framework Trace | Full Trace
app/controllers/complaints_controller.rb:252:in `complaint_params'
app/controllers/complaints_controller.rb:16:in `block in edit_status'
app/controllers/complaints_controller.rb:14:in `edit_status'
If I remark out the respond_to block, then the form works but it doesn't close when submitted.
If I leave the respond_to in (without the <% #complaint.errors.full_messages.each do |message| %> then the form simply closes.
If I have the respond_to and <% #complaint.errors.full_messages.each do |message| %> then I get the error indicated.
My log shows
Started GET "/complaints/edit_status" for ::1 at 2016-03-11 11:25:54 -0500
Processing by ComplaintsController#edit_status as HTML
[1m[35mUser Load (1.0ms)[0m EXEC sp_executesql N'SELECT [ic].[users].* FROM [ic].[users] WHERE [ic].[users].[id] = #0 ORDER BY [ic].[users].[id] ASC OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY', N'#0 int', #0 = 1 [["id", 1]]
[1m[36mComplaint Load (2.0ms)[0m [1mEXEC sp_executesql N'SELECT [ic].[complaints].* FROM [ic].[complaints] WHERE [ic].[complaints].[id] = #0 ORDER BY [ic].[complaints].[id] ASC OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY', N'#0 int', #0 = 1[0m [["id", 1]]
Completed 400 Bad Request in 13ms (ActiveRecord: 3.0ms)
ActionController::ParameterMissing (param is missing or the value is empty: complaint):
app/controllers/complaints_controller.rb:252:in `complaint_params'
app/controllers/complaints_controller.rb:16:in `block in edit_status'
app/controllers/complaints_controller.rb:14:in `edit_status'

Ruby on rails: create action doesn't work, while new, edit and update (the same form as in create !) actions works - why?

I have Realization model:
# encoding : utf-8
class Realization < ActiveRecord::Base
attr_accessible :city, :street, :title, :work, :photo, :date
has_attached_file :photo
end
Controller:
# encoding : utf-8
class RealizationsController < ApplicationController
before_filter :admin_required, :except => [:index,:show]
# GET /realization/new
def new
#realization = Realization.new
#realization.date = Time.now.__send__(:to_date).to_s
end
# POST /realization
def create
#realization = Realization.new(params[:realization])
if #realization.save
redirect_to #realization, notice: 'realization was successfully created.'
else
render action: "new"
end
end
(...) others
View of form:
<%= form_for #realization, :html => { :multipart => true } do |f| %>
<% if #realization.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#realization.errors.count, "error") %> prohibited this realization from being saved:</h2>
<ul>
<% #realization.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :title %><br />
<%= f.text_field :title %>
</div>
(...)
<div class="field">
<%= f.file_field :photo %>
</div>
<div class="actions">
<%= f.submit "Submit" %>
</div>
<% end %>
And routes :
resources :realizations
And WEBrick server info is that:
Started POST "/realizacje" for 127.0.0.1 at 2013-04-12 12:26:35 +0200
Processing by RealizationsController#index as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"zK5jP4ChBBY+R21TjrZkp4xGvCHViTFJ+8Fw6Og28YY=", "realization"=>{"title"=>"wwwwww", "street"=>"", "city"=>"", "work"=>"", "date"=>"2013-04-12"}, "commit"=>"Submit"}
(1.0ms) SELECT COUNT(*) FROM "realizations"
Realization Load (2.0ms) SELECT "realizations".* FROM "realizations" ORDER BY created_at DESC LIMIT 7 OFFSET 0
User Load (1.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 LIMIT 1
Rendered realizations/index.html.erb within layouts/application (156.0ms)
Completed 200 OK in 340ms (Views: 333.0ms | ActiveRecord: 4.0ms)
While I use the form and push the submit it redirects/randers realizations/index without notice or errors even!
I have completely no idea why? Especialy that it worked before...
Maybe javascript added later on may be the reason?
Paperclip works well in update so it isn't it...
You might check your new action to see what you're passing in to the form_for.
You want to be passing in a brand new instance of your Realization model.
i.e. in the new action you should have a line that reads #realization = Realization.new
The reason I suggest this is because form_for calls a method (#new_record?) on the object you give it and will submit a post or put request depending on whether that method call returns true or false.

Resources