Rails grouped_options_for_select not populating edit action - ruby-on-rails

I have a form with two fields where the second depends on what was selected in the first dropdown, if I select 'Asia' in the first, then 'Japan' and 'China' appear as options in the second dropdown.
.field
= f.label :country
= f.select :country, ['Asia', 'Europe'], :prompt => 'Select One'
.field
= f.label :category
= f.select :category,grouped_options_for_select(MyModel::CATEGORIES, nil, "Please Select")
The CATEGORIES variable looks like;
CATEGORIES = {
'Asia'=> [ 'Japan','China'],
'Europe'=> [ 'Ireland', 'France']
}
This works but when I go the edit page the second dropdown is not pre-populated with the stored value, how do I do this?

#dax is right but you need to explicitly set the selected value and not just the attribute. From the api
selected_key - A value equal to the value attribute for one of the tags, which will have the selected attribute set. Note: It is possible for this value to match multiple options as you might have the same option in multiple groups. Each will then get selected="selected".
Your code should be
= f.select :category, grouped_options_for_select(MyModel::CATEGORIES, f.object.category)
EDIT
The last argument passed to grouped_options_for_select should be passed to select instead and should be the value of either the prompt or include_blank option.
= f.select :category,
grouped_options_for_select(MyModel::CATEGORIES, f.object.category),
{ prompt: 'Please select' }, # here goes the select tag options
{ class: 'my-class' } # here goes the html options

you've set the selected key to nil -
MyModel::CATEGORIES, # nil #, "Please Select"
Try changing your code to this:
= f.select :category,grouped_options_for_select(MyModel::CATEGORIES, :country, "Please Select")

Related

Populate two database values from one dropdown select

I have a dropdown menu:
<%= f.collection_select :price, Print.all, :printprice, :sizetotal, {prompt: "Pick A Size & Medium"} %>
It currently populates the :price database column with the value :printprice, and shows the value :sizetotal in the actual dropdown selection.
I want to be able to populate two database columns, one of which is the :price column which is already working, but I also want to populate another column called :size with the value :printsize. I want to do this using the same dropdown select menu.
Something like:
<%= f.collection_select :price, :size, Print.all, :printprice, :printsize, :sizetotal, {prompt: "Pick A Size & Medium"} %>
But obviously the above doesnt work
Is this possible?
Following my comment, here is the ID alternative. Basically you want to send only the ID of the print, and find again the whole object on the backend during the #create or #update actions
print_for_size_and_price = Print.find(params[:print_id_for_size_and_price])
So on the frontend I'd use something like this
select_tag(
:print_id_for_size_and_price,
options_from_collection_for_select(Print.all, :id, :sizetotal)
)
And in the backend I'd do somewhere
my_instance.price = print_for_size_and_price.printprice
my_instance.size = print_for_size_and_price.sizetotal

need to add default value in f.select field to existing ones - rails 3.2

With the code I have below in the select field I have all the public_campaigns:
<%= f.select :campaign_id, #public_campaigns.map{|x| [x.name,x.id]} %>
public_campaigns is defined in controller with:
#public_campaigns = #logged_in_user.campaigns.order('created_at desc')
In the form I select the campaign and fill up the rest of the form and at the submit action an invitation is created with campaign_id taken from the campaign I selected in the form, it can be anything from 1 to n
What I need now is to have a default item in select field that will have the value of 0 and named "No campaign", it means I invite someone to a campaign that I have not created yet and in invitation the campaign_id field will be 0.
Thank you for your time.
Do you really need 0? I think use of {:include_blank => "No campaign"} should be enough?
Try this:
<%= f.select :campaign_id, (#public_campaigns.map{|x| [x.name,x.id]} << ["No campaign",0]), {:selected => 0} %>
Well, the fastest way you can do this is something like this:
#public_campaigns = #logged_in_user.campaigns.order('created_at desc')
no_campaign = Campaign.new(:id => '0', :name => 'No Campaign')
#public_campaigns.unshift(no_campaign)
I'm not sure why you are unable to do it this way:
<%= f.collection_select :campaign_id, #public_campaigns, :id, :name, prompt: 'No campaign' %>
Just check if campaign_id.nil? instead of assigning any value to campaign_id

Rails - how to validate f.select field?

I have simple select field
f.select(:name, [["- Choose Name -", 0]] + People.all.map{ |c| [c.name, c.id] })
How can I validate, if some name was selected?
I tried this rule:
validates :name, :presence => {:message => 'Name cannot be blank.'}
But if I send form without choosing the name, the form is sent...
So I would like to ask you, how can I validate the select field?
In your example, people are selecting a name, they're selecting the name - Choose Name - with id 0.
If you want to give an option that doesn't correspond to a real choice then you have two options:
f.select(:name, People.all.map{ |c| [c.name, c.id] }, :include_blank => "- Choose Name -")
f.select(:name, People.all.map{ |c| [c.name, c.id] }, :prompt => "- Choose Name -")
These are basically identical. Both will display an option at the top of the select which won't result in a value being set. However, the prompt version will only display this extra option if there isn't a current value selected, i.e. if used on an edit form it won't let the user clear their selection by setting it back to nil
Note that the include_blank method is very similar to the following code, except lots more readable:
f.select(:name, [["- Choose Name -", nil]] + People.all.map{ |c| [c.name, c.id] })

Set Selected Value on Dropdown Based on Model Property

i have a simple dropdown like :
<%= collection_select("user_cities", "city_id", current_user.cities, :id, :name ) %>
current_user.cities is an array of the user cities. Each city has a field named "is_primary" and only one city has it set as true.
My question is, how can i make the above collection_select(or transform it if needed), so that it picks the selected option, based on City.is_primary ?
From the docs:
By default, post.person_id [in your case user_cities.city_id] is the selected option. Specify :selected => value to use a different selection or :selected => nil to leave all options unselected.
Armed with that knowledge we can pass the appropriate option to collection_select:
<%= collection_select "user_cities", "city_id", current_user.cities, :id, :name,
:selected => current_user.cities.detect(&:is_primary).id
%>
collection_select("user_cities", "city_id", current_user.cities, :id, :name,{:selected => current_user.cities.where(:is_primary => 1)})
I would start by defining a method called primary_city in your User model.
def primary_city
cities.where(:is_primary => true).first
end
Then,
<%= collection_select("user_cities", "city_id", current_user.cities, :id, :name, { :selected=> current_user.primary_city.id } ) %>

collection_select set option value of :include_blank to zero

In my rails app, i have a drop down box where i retrieve all groups from the Group table and display them using the collection_select tag.
When the user selects 'None', I want to pass '0' as option value.
Currently, an empty string is passed.
Is there a way to include option value = 0 for 'None'?
<%= f.collection_select :SUB_GROUP, Group.all, :Group_ID, :Group_ID, :include_blank => 'None' %>
Many many thanks for any suggestion provided
If you use options_for_select in combination with select_tag you can achieve that using this:
options_for_select(
[['None', '0']].concat(
Group.all.collect { |g| [g.group_id.to_s, g.group_id.to_s] }
)
)
In order to keep your views uncluttered, you might want to generalize and move this into a helper method with a reasonable name.

Resources