Passing an array into hidden_field ROR - ruby-on-rails

I'm trying to pass an array into a hidden_field.
The following User has 3 roles [2,4,5]
>> u = User.find_by_login("lesa")
=> #<User id: 5, login: "lesa", email: "lesa.beaupry#gmail.com", crypted_password: "0f2776e68f1054a2678ad69a3b28e35ad9f42078", salt: "f02ef9e00d16f1b9f82dfcc488fdf96bf5aab4a8", created_at: "2009-12-29 15:15:51", updated_at: "2010-01-06 06:27:16", remember_token: nil, remember_token_expires_at: nil>
>> u.roles.map(&:id)
=> [2, 4, 5]
Users/edit.html.erb
<% form_for #user do |f| -%>
<%= f.hidden_field :role_ids, :value => #user.roles.map(&:id) %>
When I submit my edit form, I receive an error: ActiveRecord::RecordNotFound in UsersController#update "Couldn't find Role with ID=245"
How can I pass an array into the hidden_field?

I would use this technique.
<% #user.roles.each do |role| %>
<%= f.hidden_field :role_ids, :multiple => true, :value => role.id %>
<% end %>
:multiple adds both the [] to the end of the name attribute and multiple="multiple" to the input element, which is ideal. Rails uses this internally when it generates inputs for arrays, such as in fields_for.
Unfortunately it is not well-documented. I'm going to look into fixing this.

The only thing that works for me (Rails 3.1) is using hidden_field_tag:
<% #users.roles.each do |role| %>
<%= hidden_field_tag "user_role_ids[]", role.id %>
<% end %>

Try:
<% #user.roles.each_with_index do |role| %>
<%= f.hidden_field "role_ids[]", :value => role.id %>
<% end %>

using Rails 4.2.6
I was able to use
<% #user.roles.each do |role|
<%= f.hidden_field :role_ids, :id => role.id, :value => role.id, :multiple => true %>
<% end %>
which rendered:
<input id="12345" value="12345" multiple="multiple" type="hidden" name="role_form[role_ids][]">
trying to use hidden_field_tag or the 'role_ids[]' the param details were not being included in my form_params.
This didn't work:
<% #user.roles.each do |role|
<%= hidden_field_tag 'role_ids[]', role %>
<% end %>
because it renders:
<input type="hidden" name="role_ids[]" id="role_ids_" value="12345">
and is seen by the controller outside of the form params.

try with:
<%= f.hidden_field :role_ids, :value => #user.roles.map(&:id).join(", ") %>
edit: note - you'll need to do ids.split(", ") in your controller to convert them from a string into an array

I realize the original question involved a Rails form_for form, but I just encountered this problem while trying adding a hidden field to a form_tag form. The solution is slightly different.
The hidden_field_tag kept converting my ids to a space-separated string, like "1 2 3", not the array of ["1", "2", "3"] that I wanted. According to the docs, this is a known problem with hidden_field_tag. This is the approach that ended up working for my Rails 6 form_tag form:
In the view:
<%= hidden_field_tag :role_ids, my_role_ids_array %>
In the controller:
role_ids = params[:role_ids].split(' ').map(&:to_i)

Could solve this kind of issue with :
<% params[:filter].each do |filter| %>
<%= hidden_field_tag 'filter[]', filter %>
<% end %>

Related

Rails check_box_tag within form_for

Is it possible to pass the value of checked check_box_tags within a form_for in Rails inside a hash?
Here is a very generic, basic version of the form:
<%= form_for(:object, :url => { :action => 'create', :id => params[:id]}) do |f| %>
<p>Field_a: <%= f.text_field(:field_a) %></p>
<p>Field_b: <%= f.text_field(:field_b) %></p>
<p>Field_c: <%= f.text_field(:field_c) %></p>
<p>Check boxes:</p>
<% check_box_choices_object_array.each do |s| %>
<%= check_box_tag(s.name, 1, false) %>
<%= .name %><br />
<% end %>
<%= submit_tag("Create") %>
<% end %>
Outputs roughly:
Field_a ___________________
Field_b ___________________
Field_c ___________________
Check boxes:
[] box_a
[] box_b
[] box_c
[] box_d
[] box_e
[] box_f
[] box_g
My problem is that since the available check boxes aren't actual fields in the object's table in the database (i.e. I'm not using check_box(:field) in the form), each checked check box gets passed as an individual parameter (i.e. "box_a" => "1", "box_b" => "1", "box_e" => "1"). I would like them to be passed as such:
:checked_boxes => {"box_a" => "1", "box_b" => "1", "box_e" => "1"}
This way, I can access them easily with params[:checked_boxes].
How do I do this, or, better yet, is there a better solution (I'm new to rails)?
I think you'd get the results you want if you wrap the checkboxes iterator in a fields_for :checked_boxes tag - or at least get you close to the results you want.
<%= form_for(:object, :url => { :action => 'create', :id => params[:id]}) do |f| %>
<p>Field_a: <%= f.text_field(:field_a) %></p>
<p>Field_b: <%= f.text_field(:field_b) %></p>
<p>Field_c: <%= f.text_field(:field_c) %></p>
<p>Check boxes:</p>
<%= f.fields_for :checked_boxes do |cb| %>
<% check_box_choices_object_array.each do |s| %>
<%= cb.check_box(s.name, 1, false) %>
<%= .name %><br />
<% end %>
<% end %>
<%= submit_tag("Create") %>
<% end %>
you can deal with no database attributes and models using attr_accessor
class Thing < ActiveRecord::Base
attr_accessible :name
attr_accessor :box_a, :box_b, :box_c
end
This way you can call these attributes in your form.

Is there a way to set a distinct ID and name for a text_field in Rails 2?

I've got a Rails 2 site I'm trying to add a form handler to, but I'm running into problems converting the html form fields into form handler fields.
The form code begins with:
<% form_for #newsavedmap, :html=>{:id=>'createaMap'} do |f| %>
I keep getting errors when I try things like
<%= text_field :newsavedmap, :html=>{ :value => 'New Map', :name=>'newsavedmapname', :id=> 'savedmap_name', :size => '30' } %>
Error:
ActionView::TemplateError (wrong number of arguments (1 for 2)) on line #284 of app/views/layouts/maptry.html.erb:
Here are the fields. How can I convert these to form handler fields in Rails 2?
<input id="savemap_name" name="newsavedmapname" size="30" type="text" value="New Map"></p>
<select id="startdrop" name="startthere">
<OPTIONS HERE>
</select>
<select multiple id="waypoints" class="mobile-waypoints-remove" name="waypointsselected[]">
<OPTIONS HERE>
</select>
Thanks for any help you can provide!
Edit 1 Error Code for the Text_Field
Using Bigxiang's approach, I get
Processing NewsavedmapsController#create (for IP at Date Time) [POST]
Parameters: {"endhere"=>"", "endthere"=>"SAMPLE ADDRESS 1", "newsavedmap"=>{"newsavedmapname"=>"test Map"}, "startthere"=>"SAMPLE ADDRESS 2", "starthere"=>"", "optimize"=>"on"}
ActiveRecord::UnknownAttributeError (unknown attribute: newsavedmapname)
The line with "newsavedmap"=>{"newsavedmapname"=>"test Map"} should just read
"newsavedmapname"=>"test Map"
How can I do this? My controller starts with:
def create
#newsavedmap = Newsavedmap.new(params[:newsavedmap])
#newsavedmap.name = params[:newsavedmapname]
try this:
<% form_for #newsavedmap, :html=>{:id=>'createaMap'} do |f| %>
<%= f.text_field :newsavedmapname :id=>"savemap_name", :size=>30, :value=>"New Map"%>
<%= f.select :startthere, YOUR_COLLECTIONS, {}, {:id=>"startdrop"}%>
<%= f.select :waypointsselected, YOUR_COLLECTIONS, {}, {:id=>"waypoints", :class=>"mobile-waypoints-remove", :multiple => true}%>
<% end %>
make sure YOUR_COLLECTIONS should be an array like ['a', 'b', 'c'] or [['name1', id1],['name2', id2],['name3', id3]].
If you persist the parameter is "newsavedmapname"=>"test Map", try this:
<% form_for #newsavedmap, :html=>{:id=>'createaMap'} do |f| %>
<%= text_field_tag :newsavedmapname, "New Map", :id=>"savemap_name", :size=>30%>
<%= select_tag :startthere, options_for_select(YOUR_COLLECTIONS), {:id=>"startdrop"}%>
<%= select_tag :waypointsselected, options_for_select(YOUR_COLLECTIONS), {:id=>"waypoints", :class=>"mobile-waypoints-remove", :multiple => true}%>
<% end %>
But I don't understand why not use parameter's name as same as the column's name. For example, I see your newsavedmap model has a column named "name". you can use it directly
<% form_for #newsavedmap, :html=>{:id=>'createaMap'} do |f| %>
<%= f.text_field :name , :value=>"New Map" %>
<% end %>
in your controller , you can delete line #newsavedmap.name = params[:newsavedmapname]
def create
#newsavedmap = Newsavedmap.new(params[:newsavedmap])
if #newsavedmap.save
#######
end
end

Rails - creating multiple records, not all params are being passed

I'm trying to add multiple product skus to an order at once.
Product has_many skus,
Order has_many order_lines
So in my order, I pull up a product and see all its skus (brown-small, brown-large) I then enter the qty of each I want to put on the order.
For some reason, it is only passing the :qty_sold params, and not the :sku_id - any reason why?
Routes:
post '/order_lines/create' => 'order_lines#create', :as => :create_order_lines
Form:
<%= form_tag create_order_lines_path do %>
<%= hidden_field_tag :order_id, #order.id %>
<% #product.first.skus.each_with_index do |sku, index| %>
<%= text_field_tag "order_lines[#{index}]", :sku_id, {:value => sku.id } %>
<%= sku.colour %>
<%= text_field_tag "order_lines[#{index}]", :qty_sold, {:value => ''} %>
<% end %>
<%= submit_tag "Add" %>
<% end %>
Output:
Started POST "/order_lines/create" for 127.0.0.1 at Fri Mar 16 23:13:27 -0400 2012
Processing by OrderLinesController#create as HTML
Parameters: {"commit"=>"Add", "order_id"=>"1", "authenticity_token"=>"JmImxbFUGLdM6Vt0rrS9RabSCUi1kV2QRTpWp34BBb4=", "utf8"=>"\342\234\223", "order_lines"=>{"0"=>"7", "1"=>"8", "2"=>"", "3"=>"9", "4"=>"", "5"=>""}}
This line is setting the key that you're having problems with
text_field_tag "order_lines[#{index}]"
So basically you're saying order_lines[X] = and since :qty_sold is the last option set to that key it's getting assigned that value.
To accomplish what you're trying to accomplish you would need to go a level deeper, like this
<%= text_field_tag "order_lines[#{index}][qty_sold]", :qty_sold, {:value => ''} %>
Honestly though, you should consider looking into the fields_for helper it does everything you want to accomplish and is more abstract.
This is untested but I think it should work
<% #product.skus.each do |sku| %>
<%= fields_for :order_lines do |order_line_fields| %>
<%= order_line_fields.text_field :sku_id, {:value => sku.id} %>
<%= sku.colour %>
<%= order_line_fields.text_field :qty_sold %>
<% end %>
<% end %>

Get an array from a Rails form

I need to design a form for a account resource. In that form, i need to collect some set of ids as an array in the params hash in attribute called relationships.
So the final params[account] hash from the POST request should be like:
{:name => 'somename', :relationships => ["123", "23", "23445"]}
How shall I design the form_for fields? I tried this, but didn't work:
<%= form_for #account do |f| %>
<%= f.text_field :name %>
<% #eligible_parents.each do |p| %>
<%= f.check_box "relationships", nil, :value => p.id %>
<b><%= p.name %></b><br/>
</span>
<% end %>
<%= f.submit "Submit" %>
<% end %>
Number of elements in #eligible_parents varies every time.
relationships is neither an association nor an attribute in account model.
I have to use virtual attributes but I need to fill in an array from a form.
Please help. How can I do this?
You still need a fields_for in your view, just use :relationships as the record_name then provide an object.
<%= form_for #account do |f| %>
<%= f.text_field :name %>
<% fields_for :relationships, #eligible_parents do |p| %>
<%= p.check_box "relationships", nil, :value => p.object.id %>
<b><%= p.object.name %></b><br/>
<% end %>
<%= f.submit "Submit" %>
<% end %>
Documentation here: ActionView::Helpers::FormHelper
I found this to be the cleanest way...
If you are working with straight data and want to send back an array without using any of these #objects:
<%= form_for :team do |t| %>
<%= t.fields_for 'people[]', [] do |p| %>
First Name: <%= p.text_field :first_name %>
Last Name: <%= p.text_field :last_name %>
<% end %>
<% end %>
your params data should return like this:
"team" => {
"people" => [
{"first_name" => "Michael", "last_name" => "Jordan"},
{"first_name" => "Steve", "last_name" => "Jobs"},
{"first_name" => "Barack", "last_name" => "Obama"}
]
}
If you want to send array of values just use [] in name attributes.In your case just use
<%= f.check_box "relationships", {}, :value => p.id, :name => "relationships[]" %>
In a complex form, with nested attributes, you can make use of the f.object_name helper. But beware of the syntax when doing interpolation. This is correct:
"#{f.object_name}[relationships][]"
This is NOT correct:
"#{f.object_name}[relationships[]]"
It always trips me up.
I'm working in something similar. My issue was how to pass the input name to a partial to resolve it as a hash using the rails form_for helper.
So, my solutions was something like this:
= render 'my_partial', form: form, name: "item_ids[item.id]"
So, this gonna render an html like this:
<input class="form-control" name="products[items_ids[1]]" id="products_items_ids[1]">
The number 1 is the item.id, this is how HTML understand that you gonna pass an array or hash, all depends your config.
So, the params gonna look like this:
"items_ids"=>{"1"=>"1"}
This is working for me with an form_object + virtus

A Many-Many Association Hidden_Field edit problem. ROR

I'm trying to pass an array into a hidden_field.
The following User has 3 roles [2,4,5]
>> u = User.find_by_login("lesa")
=> #<User id: 5, login: "lesa", email: "lesa.beaupry#gmail.com", crypted_password: "0f2776e68f1054a2678ad69a3b28e35ad9f42078", salt: "f02ef9e00d16f1b9f82dfcc488fdf96bf5aab4a8", created_at: "2009-12-29 15:15:51", updated_at: "2010-01-06 06:27:16", remember_token: nil, remember_token_expires_at: nil>
>> u.roles.map(&:id)
=> [2, 4, 5]
Users/edit.html.erb
<% form_for #user do |f| -%>
<%= f.hidden_field :role_ids, :value => #user.roles.map(&:id) %>
When I submit my edit form, I receive an error: ActiveRecord::RecordNotFound in UsersController#update "Couldn't find Role with ID=245"
Next I attempted to edit my users/edit.html.erb to:
<%= f.hidden_field :role_ids, :value => #user.roles.map(&:id).join(", ") %>
Yielding what I believe is a string: "role_ids"=>"2, 4" (Required Output: "role_ids"=>["2", "4"])
When I attempted using a loop:
<% for role in Role.find(:all) %>
<%= f.hidden_field :role_ids, :value => #user.roles.map(&:id).join(",").to_a %>
<% end %>
Yet another string resulted:
Parameters: {"commit"=>"Update", "action"=>"update", "_method"=>"put", "authenticity_token"=>"84Fvxxo3ao8Fl+aytOFInrLatUpslfAJggleEyy4wyI=", "id"=>"5", "controller"=>"users", "user"=>{"password_confirmation"=>"[FILTERED]", "role_ids"=>"2, 4, 5", "password"=>"[FILTERED]", "login"=>"lesa", "email"=>"lesa#gmail.com"}}
Any suggestions? This has been a perplexing problem.
If you want to submit an array of values I believe you can do something like this:
<% #user.roles.each do |role| %>
<%= f.hidden_field 'role_ids[]', :value => role.id %>
<% end %>
Rails should then merge the value of each hidden field with the same name 'role_ids[]' into an array giving you something like this:
Parameters: {"commit"=>"Update" ... "role_ids"=>["2", "4", "5"], ... }}
The accepted answer doesn't work for me. It works if you're using hidden_field_tag but not with f.hidden_field. I need to resort to
<%= f.hidden_field 'role_ids][', value: role.id %>
Note the reversed bracket.
if you pass just the u.roles.map(&:id)[0] what happens? is the value = 2? Maybe the value don't accept multivalue or maybe you should pass
<%= f.hidden_field :role_ids, :value=>“#{u.roles.map(&:id).join(',')}">
You could do the work in the controller edit action (air code):
#role_ids = #user.roles.map(&:id).join(";")
In the form:
<%= f.hidden_field, 'role_ids', :value => #role_ids %>
Then in the update action:
roles = params[:user][:role_ids].split(";")

Resources