Collection Select Helper in Rails 3 - ruby-on-rails

I have a quick question in regards to the collection_select helper in Rails 3.
I would like to create a drop down field whereby a user can select a country from a list.
My code currently looks something like this:
<%= collection_select(:country,:id,SyncedCountry.order('name ASC'),:name,:name,{},{:class => "input-xlarge"}) %>
When I submit on the page I see something like this in the params for country:
"country"=>{"id"=>"Antilles"}
What I really want is the id of the country selected in the drop-down and not in a hash format. So the result would be more like:
"country"=> 1 (the id of a country selected)
Any ideas?

Replace
<%= collection_select(:country,:id,SyncedCountry.order('name ASC'),:name,:name,{},{:class => "input-xlarge"}) %>
with
<%= collection_select(:model_object,:country,SyncedCountry.order('name ASC'),:name,:name,{},{:class => "input-xlarge"}) %>
where model_object is the object passed to form. If its a form for user and your form looks like form_for(#user) then replace :model_object with :user.
So, params would look like "user"=>{"country"=>"Antilles"}, assuming that you are setting country for a user.

From the documentation:
collection_select(object, method, collection, value_method, text_method, options = {}, html_options = {}) public
...
The :value_method and :text_methodparameters are methods to be called
on each member of collection. The return values are used as the value
attribute and contents of each <option> tag, respectively. They can
also be any object that responds to call, such as a proc, that will be
called for each member of the collection to retrieve the value/text.
So try:
<%= collection_select(:country,:id,SyncedCountry.order('name ASC'),:id,:name,{},{:class => "input-xlarge"}) %>
The example in the documentation looks like this:
Sample usage (selecting the associated Author for an instance of Post,
#post):
collection_select(:post, :author_id, Author.all, :id,
:name_with_initial, prompt: true)
If #post.author_id is already 1, this would return:
<select name="post[author_id]">
<option value="">Please select</option>
<option value="1" selected="selected">D. Heinemeier Hansson</option>
<option value="2">D. Thomas</option>
<option value="3">M. Clark</option>
</select>
(this will return "author_id"=>"1")
Now, I'm not familiar with your model, but if you are selecting the country of your user, than I think this should work:
<%= collection_select(:user, :country_id,SyncedCountry.order('name ASC'),:id,:name,{},{:class => "input-xlarge"}) %>

Related

ruby on rails - drop down list from model

I would like to create a drop down list with Ruby on rails from the model "Company" which has a item call "name". I would like to length of the dropdown list to be as long as Company.count (dynamic)
For example for 3 element in "Company":
<%= f.select :company_brand, [[Company.find(1).name, Company.find(1).id],[Company.find(2).name, Company.find(2).id],[Company.find(3).name, Company.find(3).id]]%>
collection_select (documentation) will provide what you need:
collection_select(object, method, collection, value_method, text_method, options = {}, html_options = {})
Returns and tags for the collection of existing return values of method for object's class. The value returned from calling method on the instance object will be selected. If calling method returns nil, no selection is made without including :prompt or :include_blank in the options hash.
The :value_method and :text_method parameters are methods to be called on each member of collection. The return values are used as the value attribute and contents of each tag, respectively. They can also be any object that responds to call, such as a proc, that will be called for each member of the collection to retrieve the value/text.
For your use case, this would mean changing the code to:
<%= f.collection_select(:company_brand, Company.all, :id, :name) %>
You can do like this:
<%= select(:company_brand, Company.all.collect {|c| [ c.name, c.id ] }, { include_blank: true }) %>
#League - form.html.erb
<%= f.collection_select(:game_id, Game.order(:title), :id, :title, {prompt: true}, {class: 'form-control col-md-7 col-xs-12', required: "required"})%>
#.html_output
<select class="form-control col-md-7 col-xs-12" required="required" name="league[game_id]" id="league_game_id"><option value="">Please select</option>
<option value="2">csgo</option>
<option value="1">dota2</option>
</select>
You can try this i think this will help you.
<%= f.select :company_brand, options_from_collection_for_select(Company.all, "id", "name") %>

Rails collection_select with join table

My tables:
Person belongs_to and
Room has_many Person
My collection_select
<%= collection_select(:inspection, :person_id, Person.involving(current_user), :id, :room_id) %>
If I'm not wrong, in HTML it will be represented as the following code:
<select name="post[person_id]">
<option value="<%= person.id %>"><%= person.room_id %></option>
<% end %>
</select>
My point is that when a user submit the form I need send the Person Id value, but I need show on the drop down list the name of the rooms (in my example I showing the room.id) like that:
<select name="post[person_id]">
<option value="<%= person.id %>"><%= room.name %></option>
<% end %>
</select>
How can I do that?
As I see I think that I need join person table with room table? If it is the solution, how can I do that?
My person model:
scope :involving, -> (user) do
where("persons.id = ?", user.id)
end
My view
<%= form_for #inspection do |f| %>
<label>Select</label>
<%= collection_select(:inspection, :person_id, Person.involving(current_user), :id, :room.id) %>
<%= f.submit "Send" %>
I tried to make it as clear as I could.
Consider using select rather than collection_select. This method allows you finer grain control over what is used for id and name of each option.
In your case you'd want something like:
select(:inspection, :person_id, Person.involving(current_user).collect {|p| [ p.id, p.room.name ] }, { ...other method options... })
This allows you to specify the array of option id/name pairs. You get all the people involved using your scope, then iterate over those returning an array for each one found, where the first value in the array is the option value and the second is the displayed option text.
Check this documentation out for more details.

collection_select with multipe true sends params with an empty string

The select_options tag in my application generates a param list which always contains an empty string at the beginning.
This leads to an error when the params are used to fetch data from database.
the form part is like this:
<%= f.label :text %><br>
<%= f.text_area :text, cols: 80, rows: 15, class: 'form-control' %>
<%= f.label 'Category:' %>
<%= f.collection_select(:categories, Category.all, :id, :cat_name, {:selected => Category.first.id}, {:multiple => true}) %>
the output (html) is like this:
<select multiple="multiple" name="article[categories][]" id="article_categories">
<input name="article[categories][]" value="" type="hidden">
<option selected="selected" value="1">default</option>
<option value="2">politics</option>
</select>
That looks perfect to me. But when submitted (with the two options selected) the parameters look like this:
Parameters: {"utf8"=>"✓", "authenticity_token"=>"kvYo6rb+lswUuJMHpbb+hH3YFjHU25/ESN7vvLLdlVn1TOSgzyiMsXkrJbiWIhuuO4UvNLQ3jU7uTw0zneVTUA==",
"article"=>{"title"=>"test category", "text"=>"Na mal sehen...\r\nIses drin?",
"categories"=>["", "1", "2"], "published"=>"0"}, "commit"=>"Save changes", "id"=>"76"}
The categories part contains: categories"=>["", "1", "2"]
The first is an empty string and i cant figure out how to get rid of it.
Thanks for help in advance!
Rails generates a hidden field which has the same name as the select field, so that if no options are selected a value is still submitted. You can prevent Rails from adding the hidden field by specifying include_hidden: false for the collection_select.
Here is an excerpt from the explanation (link):
To prevent this the helper generates an auxiliary hidden field before
every multiple select. The hidden field has the same name as multiple
select and blank value.
Note: The client either sends only the hidden field (representing the
deselected multiple select box), or both fields. This means that the
resulting array always contains a blank string.
In case if you don’t want the helper to generate this hidden field you
can specify include_hidden: false option.
Wizard's solution have some negative effects: we can not empty the fields once we set.
I found that we can config the strong parameter like following to fix the problem:
params.require(:article).permit(categories: []);
I found that permit(:categories) not work but permit(categories: []) works.

how do i get the id of the selected item in dropdown

<%= form_for(:offer,:url=>{:controller=>'offers',:action=>'combo'}) do |f|%>
<%= f.select :catId_get, options_from_collection_for_select(#categories, "id", "name"), prompt: "Select Category" %>
I am new in rails.I have a dropdown where all categories are there.When i select a category from this dropdown i want to get its category id in my controller,so that i can use that id for it's child dropdown.
Select
Each select option in HTML has two values -- the value and the label:
<select>
<option value="volvo">Volvo</option>
<option value="saab">Saab</option>
<option value="mercedes">Mercedes</option>
<option value="audi">Audi</option>
</select>
It's only the value which is passed to your controller. This means if you are able to create the select tag in your Rails app with the correct value / label setup, it will pass the correct data you require.
Rails
Here's how I'd handle it:
<%= form_for :offer, offers_combo_path do |f|%>
<%= f.collection_select :cat_id, #categories, :id, :name, prompt: "Select Category" %>
This will pass the following params to your categories_controller:
#app/controllers/categories_controller.rb
class CategoriesController < ApplicationController
def combo
params[:offer][:cat_id]
end
end
Recommendation
I'd actually recommend you use the form_tag helper for this, rather than form_for. Reason being that form_for is mainly for ActiveRecord objects, and although you can use :symbols in the helper, you will really need to use a much less elaborate system
I'd just replace your form_for with the following:
<%= form_tag offer_combo_path do %>
<%= collection_select :cat_id, #categories, :id, :name, prompt: "Select Category" %>
<% end %>
Your id should be accessible by
params[:offer][:catId_get]
in your controller.

Ruby on Rails: Submitting a form referring to another controller via collection_select

Today is the first day I'm looking into Ruby on Rails, and now I'm stuck. I have two scaffolds, artist and song.
In songs/new.html.erb, I have these lines:
...
<%= f.label :name %><br />
<%= f.text_field :name %>
...
<%= f.label :Artist %>
<%= collection_select(:song, :Artist, #artists, :id, :sort_name) %>
...
In the form for creating a new song, I want a <select> list with all artists. Using the code above works fine. The form is created as I want it, and the artists are listed. However, when submitting the new song, I get this error:
Artist(#69916999335860) expected, got String(#69917057438720)
The generated HTML code for the select looks like this:
<select id="song_Artist" name="song[Artist]">
<option value="1">Vreeswijk, Cornelis</option>
<option value="2">De lyckliga kompisarna</option>
<option value="3">Wiehe, Mikael</option>
<option value="4">Demian, Lars</option>
<option value="5">Sundström, Stefan</option>
</select>
I guess the second last parameter for collection_select() is wrong, but what should it be?
I think this should be:
<%= collection_select(:song, :artist_id, #artists, :id, :sort_name) %>
The second parameter is the method to be assigned in the model being created/updated. So in your controller the value would be retrieved from the params hash with params[:song][:artist_id]
A detailed explanation can be found in the Rails API docs under "collection_select"

Resources