Rails - how to validate f.select field? - ruby-on-rails

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] })

Related

I am using a form select in ruby on rails. How do I get the blank default to show prompt message?

= f.select :from_id, decorated_froms.map { |from| [from.name, from.id] }, include_blank: "Please select a role to send a message."
include_blank
<%= f.select :from_id, decorated_froms.map { |from| [from.name, from.id] }, include_blank: 'Please select a role to send a message.') %>
This will always include a blank option in the select, which will allow people to set the value back to the blank value if they're seeing this on an edit form.
prompt which is the better option
<%= f.select :from_id, decorated_froms.map { |from| [from.name, from.id] }, prompt: 'Please select a role to send a message.') %>
This will include the specified prompt value, so long as the field hasn't already been set. If it has (on an edit form for example), there's no need to remind the user that they need to select a value so the prompt doesn't appear.
More on #select https://apidock.com/rails/ActionView/Helpers/FormOptionsHelper/select

include blank : true not working in select rails

<%= select :used_car, :car_make_id, #all_makes.map { |m| [m.title, m.name] }, {:include_blank => true,:prompt=>"Select Make"}%>
<%= select :used_car, :car_model_id, [], {:include_blank => true,:prompt=>"Select Model")}, size: 10, :class=>"form-control select"%>
Car models list updating on basis on car make selection
Issue is that when I select car make, prompt of car model remove and first option come
how i resolve it?
Here is the documentation.
http://api.rubyonrails.org/classes/ActionView/Helpers/FormBuilder.html#method-i-select
http://api.rubyonrails.org/classes/ActionView/Helpers/FormOptionsHelper.html#method-i-select
Try f.select :car_model_id, ... instead. Also try using nil for choices, or [[]] for choices.
But first, you have an extra stray parenthesis ')' in this line:
<%= select :used_car, :car_model_id, [], {:include_blank => true,:prompt=>"Select Model" ) }
You have to remove that parenthesis. It doesn't go with anything.

Rails grouped_options_for_select not populating edit action

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")

Validates the presence of an option

I have a form that I want to validate if an option has been selected.
I do not want to accept the default starting option, "Please Select a Product"
I using this now and get a uninitialized contant error. I believe I am writing the syntax wrong.
Controller:
validates :product_name, :presence => { :unless => (product_name = "Please Select a Product")}
View:
<span class="span5 pagination-right">
<%= f.label "Product" %>
<%= f.select :product_name, options_for_select([ ["Please Select a Product"] ]) %>
</span>
How am I supposed to have the option written?
Thank you
The product_name is changed like this:
<script>
$(document).ready(function() {
$('#ticket_product_name').html("<option>Please Select a Product</option>");
$('#ticket_firmware_version_string').html("<option>Please Select a Firmware</option>");
$('#category').change(function(){
$('#ticket_product_name').html("<option>Please Select a Product</option>");
$('#ticket_firmware_version_string').html("<option>Please Select a Firmware</option>");
if ($('#category').val() == "blah")
{
$('#ticket_product_name').append("<option>blah</option>");
$('#ticket_product_name').append("<option>blah</option>");
}
else if ($('#category').val() == "another category")
{
$('#ticket_product_name').append("<option>blah product</option>");
}
until end of options, end script.
I think what you are looking for is a placeholder for this select. In this case, I used a disabled option:
<% options = options_for_select(["Select an option", ["Product #1",1], ["Product #2",2]], disabled: "Select an option") %>
<%= f.select :product_name, options %>
You should use include_blank from the select helper, like this:
<%= f.select :product_name, options_for_select([["opt1",1],["opt2",2]]), include_blank: true %>
and then, on model
validates :product_name, :presence => true
#MrYoshiji commented something truthful in my answer - if you are not allowing it to be blank, the easy way is simply not add a blank option in the select
I would recommend to use the :prompt option for your select helper (the documentation on this isn't quite straight forwward, but it's ok in this version of the same thing: http://apidock.com/rails/ActionView/Helpers/FormTagHelper/select_tag). This allows you to define a helper string of text to encourage the user to select an option, but will submit a nil value back when the form is submitted.
<%= f.select :product_name, PRODUCT_NAME_OPTIONS, prompt: 'Select an option' %>
The next thing I'd recommend is... instead of validating presence of on the model, do a validates_inclusion_of. This way you can define the set of options in the model and then use that same set of options in the select helper, above, as well is in your validation. This way you know the form wasn't manipulated to include a different option and it actually keeps things a bit DRYer.
Product
PRODUCT_NAME_OPTIONS = {'opt 1' => 'opt1', 'opt 2' => 'opt2'}
validates_inclusion_of :product_name, :in => PRODUCT_NAME_OPTIONS.values, :message => 'choose from the available options'
Instead of making this too complicated, I just added a length validation since the default is much longer then the product names. Simple is best, however there should be a string validator option.
validates :product_name, presence: true, length: {
maximum: 21,
too_long: ": Must select a product"
}

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 } ) %>

Resources