I am trying use gem 'best_in_place' in table edit, but having error while using it
in controller only index method for display all users details from db.
Error: undefined method name' for "Rohit":String`
Code used:
<% #user_record.each do |record| %>
<tr>
<td><%= best_in_place record.name, :name %></td>
</tr>
<% end %>
controller Code:
def index
#user_record = MUser.search(params[:name],params[:gender])
end
def create
end
as I see from the docs the first argument you pass to the method best_in_place should be an object record and the second - a field you need to edit with this gem, in your case it is name.
So it will get provided field name from the record.
And since you've called name by yourself, it returns the actual value of the name instead of the whole object record and then tries to get name from that value which results in this error.
So you need to change that line to <td><%= best_in_place record, :name %></td>.
Related
I have a show page where I need to both show the student's units and create a unit for them. However an error is being incurred when trying to do both.
In my controller
def show
#student = Student.find(params[:id])
#unit = #student.units.build
#units = #student.units
end
In my view
<%= simple_form_for #unit, url: student_units_path(#student) %>
# form...
<% end %>
<% #units.each do |unit| %>
<tr>
<td><%= unit.course %></td>
<td><%= unit.mailing_date.strftime('%m/%d/%y') %></td>
</tr>
<% end %>
The unit.course call works and any call that is only the first child of unit, however when I call a second method on unit I get this error:
undefined method `strftime' for nil:NilClass
despite knowing that the unit exists, hence the first call working
It seems your issue is that unit.mailing_date is nil, for newly-built records.
One solution would be to define a default value for mailing_date, either at the database level or in your application. For example, you could do something like:
class Unit < ActiveRecord::Base
# ....
after_initialize :set_default_mailing_date
private
def set_default_mailing_date
self.mailing_date ||= Date.today
end
end
Or alternatively, you could leave the mailing_date as nil and handle this gracefully in the view:
<td><%= unit.mailing_date.try!(:strftime, '%m/%d/%y') %></td>
If you are using ruby version 2.3+, then I would advise using the built-in safe navigation operator, rather than ActiveSupport's try! method:
<td><%= unit.mailing_date&.strftime('%m/%d/%y') %></td>
Finally, if you went with the above choice to leave the mailing_date as nil, then perhaps you'd like to display some default value in its place - for example:
<td><%= unit.mailing_date&.strftime('%m/%d/%y') || 'Not set' %></td>
As an alternative, I assume you don't want the new unit bound to the form being rendered which is what is causing the error.
You could do
#units = #student.units.reject(&:new_record?)
To remove the newly built unit from the collection
On my landing_pages "show" page, I'm trying to show the leads that came in via that page and sort them via their "score".
My landing_page model has:
has_many :page_leads
My page_lead model has:
belongs_to :landing_page
In my index method within my page_leads controller, I have this, which works:
def index
#page_leads = PageLead.order(score: :desc)
end
I try to duplicate this in the landing_pages controller for the show method. Here is what I have:
def show
#landingpage = LandingPage.find(params[:id]).order(score: :desc)
end
When I try to go to the "Show" page, I get an error "undefined method `order' for "1":String". How can I get this to work?
My show page has the following code:
<tbody>
<% #landingpage.page_leads.each do |page_lead| %>
<tr>
<td><%= page_lead.fname %></td>
<td><%= page_lead.lname %></td>
<td><%= page_lead.score %></td>
</tr>
<% end %>
</tbody>
It is just:
def show
#landingpage = LandingPage.find(params[:id])
end
Cause find returns the LandingPage with id == params[:id]. No need to sort a single item.
find returns an array or records if the params[:id] is an array.. the order can't be applied to the array, because order isn't part of the array class.
If params[:id] is a single element then the find returns the record. Again order doesn't apply, because it's just one record not a container of records..
If you want an sorted list then use
LandingPage.where(id: params[:id]).order
But since this is in the show I suspect you want the single item... As spickermann said drop the order
LandingPage.find(params[:id])
If you want to sort Page Leads, you would do something like
def show
#landingpage = LandingPage.find(params[:id])
#page_leads = #landingpage.page_leads.order(score: :desc)
end
As #spickermann mentioned, .find() only returns one model instance. You can't order this using ActiveRecord query methods.
If you want to order the page leads, you have to call .order on the set of page_leads that belong to the landing page
I have a form where I want a checkbox selection to override the user's selected value for another attribute.
The form:
<%= form_for(#foo) do |f| %>
<tr>
<th>FooType</th>
<td><%= f.select :foo_type_id, options_from_collection_for_select(FooType.order(:name).all, "id", "name", #foo.cabinet_type_id) %></td>
</tr>
<tr>
<th>Legacy Foo</th>
<td><%= f.check_box :is_legacy %> </td>
</tr>
Where do I put code to overwrite the user's selection for :foo_type based on if :is_legacy is checked? I tried adding an update_attribute command after saving the new Foo, but it doesn't seem to work:
if #foo.save_standard and ! row.nil?
#set foo type to 38u when it is a legacy foo
if params[:is_legacy] == true
#foo.update_attribute(foo_type_id, 2)
end
I think there are a couple of mistakes in the following code:
if #foo.save_standard and ! row.nil?
#set foo type to 38u when it is a legacy foo
if params[:is_legacy] == true
#foo.update_attribute(foo_type_id, 2)
end
end
Try:
if #foo.save_standard && row
if params[:foo][:is_legacy]
#foo.update_attribute(:foo_type_id, 2) # careful, this method do not fire callbacks
end
end
Assuming your instance object is a Foo class (which is probably not). If not, replace
params[:foo]
by whatever your instance class is.
I am trying to pass an rfid_tag from a form that creates a device from a hidden_field. Device has_many rfids. The rfid already exists in the db.
Here is the code from the form:
<th>RFID Tag #</th>
<td>
<%= f.label(:#passed_rfid_tag, #passed_rfid_tag) %>
<%= f.hidden_field :rfid_tag, :value => #passed_rfid_tag %>
</td>
</tr>
Here is the code from the devices_controller:
def create
#cabinet = Cabinet.find(params[:device][:cabinet_id])
#device = Device.create(params[:device])
#device.rfids << Rfid.where('rfid_tag' => params[:rfid_tag]).first
#device.row_id = #cabinet.row_id
#device.save
I get the following error because rfid_tag is not an attribute of device. It is an attribute of rfid:
Can't mass-assign protected attributes: rfid_tag
app/controllers/devices_controller.rb:182:in `create'
Thanks.
The mass-assign error is happening because you are passing :rfid_tag as part of the params[:device] attribute hash.
In your example code, the :rfid_tag field needs to be provided using the hidden_field_tag form helper. This will keep it from being included in the params[:device] hash.
<tr>
<th>RFID Tag #</th>
<td>
<%= label_tag 'rfid_tag', 'RFID Tag' %>
<%= hidden_field_tag 'rfid_tag', #passed_rfid_tag %>
</td>
</tr>
You can then access it via params[:rfid_tag]. Your create method should still work.
Do what Dan Reedy said and use a hidden_field_tag in your form.
I'm concerned about this line in your controller's create method:
#device.rfids << Rfid.where('rfid_tag' => params[:rfid_tag]).first
That's good if your rfid also has many devices, so you have a many to many relationship. If an rfid tag goes with exactly one device though you'll probably need to change that to something like:
rfid = Rfid.where('rfid_tag' => params[:rfid_tag]).first
rfid.device_id = #device.id
rfid.save!
And of course be sure to handle the cases where the cabinet_id or the rfid_tag you get from the params hash are not found in the database. Can't ever count on user provided input to be valid or correspond to real records, even if it's from hidden fields.
Rails 2.3.5
I have a view displaying 'employee' records in a table where each table row haas a check_box_tag to select that (row) employee record (the table is inside a form_tag). The checkbox is passing an array of employee numbers to a method but I also need it to pass some of the other information from the record (first_name, last_name, etc) in the params.
Orignally this looked like (just passing an param with an array of employee numbers)
<% #employee_search.each do |e| %>
<td><%= check_box_tag 'selected_subordinates[]', e.employee_number %></td>
<td><%= e.employee_number %></td>
<td><%= e.first_name %></td>
<td><%= e.last_name %></td>
...
<% end %>
I'm not sure this was right, but I thought I should pass the entire record ('e') in the param:
<% #employee_search.each do |e %>
<td><%= check_box_tag 'selected_subordinates[]', e %></td>
<td><%= e.employee_number %></td>
<td><%= e.first_name %></td>
<td><%= e.last_name %></td>
...
<% end %>
The param array now looks like:
"selected_subordinates"=>["#<Employee:0xa946970>", "#<Employee:0xa946910>", "#<Employee:0xa9468b0>"]
I thought at this point I would be fine and just itterate through the objects in the param array referring to the record fields, but got an undefined method error:
params[:selected_subordinates].each do |s|
puts s.last_name
end
undefined method `last_name' for "#<Employee:0xa946970>":String
I started wondering if for some reason the entire model object was passed instead of just one record from the object. But, trying [0].last_name resulted in a different error.
params[:selected_subordinates].each do |s|
puts s.last_name
end
undefined method `last_name' for 35:Fixnum
Maybe I should have been using the fields I need to build an array for the param - so the param would be an array of arrays? I haven't had any luck so far trying to search for example of what to do when you need to setup a param array made of arrays, or pass a single model object record (and refer to it).
Thank You - Much Appreciated!
When you used e as the param, Rails was converting e to a String and passing that (you can't pass an object in an HTML form, right? Just values). When you saw "#<Employee:0xa946970>" in your params hash, it wasn't an Employee object, but instead a String with the contents of #<Employee:0xa946970> (which is what you get if you called .to_s on an Employee object).
Passing the ID gets you on the right track, but once you have the ID, you should look up the Employee with that ID from the database.
params[:selected_subordinates].each do |s|
employee = Employee.find(s)
puts employee.last_name
end
Of course, this loads them one at a time, so if you have a lot of checkboxes you could end up generating a large number of queries. You can also use the find method to find multiple objects based on an array of IDs:
employees = Employee.find(params[:selected_subordinates])
employees.each do |e|
puts e.last_name
end