rails form select multiple gives empty first value - ruby-on-rails

I have defined has_and_belongs_to_many associations between Meals and Recipes. In the Meals create form, I am using a select to populate the recipes.
<%= f.select :recipes, Recipe.all.collect { |x| [x.name, x.id]}, {}, :multiple => true %>
But the result set has a nil as the first value.
"recipes"=>["", "2", "7"]
How can I eliminate the empty/nil value?

For me setting :include_hidden => false is what worked
<%= f.select :recipes, Recipe.all.collect { |x| [x.name, x.id]}, {:include_hidden => false}, :multiple => true %>

You can reject blank option by passing :include_blank => false
<%= f.select :recipes, Recipe.all.collect { |x| [x.name, x.id]}, {:include_blank => false}, :multiple => true %>
And you can set an prompt as following
<%= f.select :recipes, Recipe.all.collect { |x| [x.name, x.id]}, {:include_blank => "Please Select"}, :multiple => true %>

Related

Rails undefined method `map' for nil:NilClass on collection_select - The reference called may be nil

After reading through the other SO answers, it's pretty clear that there are some common themes.
Mostly this type of error seems to happen when the object called is not defined yet, but in this case we have a has_many relationship that may not have a referenced entry when building the selection.
Class Tag
property :name, type: String
has_many :in, :tagged, type: :CONCEPTUAL_TAG, model_class: :Artefact
end
One option is to do something like this:
<div class="field">
<%= f.label :tagged_id %><br>
<% if !#tag.tagged.empty? %>
<%= f.collection_select(:tagged, Artefact.all.sort { |a,b| a.name <=> b.name }, :id, :name, options = {:prompt => "Please Select an Item", :selected => #tag.tagged.map(&:id)}, html_options = {:multiple => true, :class=>"search"}) %>
<% else %>
<%= f.collection_select(:tagged, Artefact.all.sort { |a,b| a.name <=> b.name }, :id, :name, options = {:prompt => "Please Select an Item"}, html_options = {:multiple => true, :class=>"search"}) %>
<% end %>
</div>
But this is definitely not DRY.
Is there a way to select nothing when there is no association, and pre-populate when there is while keeping to a single f.collection_select?
You don't have to use the condition in your view. Even if there are no items in #tag.tagged, it is still an ActiveRecord::Relation instance, so you can go ahead and just call map on it:
<%= f.collection_select(:tagged,
Artefact.all.sort { |a,b| a.name <=> b.name },
:id,
:name,
options = {
:prompt => "Please Select an Item",
:selected => #tag.tagged.map(&:id)
},
html_options = {
:multiple => true,
:class=>"search"
})
%>

Rails Ransack include blank in multiple select

I'm using the gem Ransack in a Rails 3.2 app.
The following works to select multiple values:
<td><%= f.collection_select :costproject_coststatus_id_in, Coststatus.all, :id, :statuscode, {}, { :multiple => true}
But, is there a way to include a blank?
I've tried these:
<td><%= f.collection_select :costproject_coststatus_id_in, Coststatus.all, :id, :statuscode, {}, { :multiple => true, :include_blank => true }%></td>
<td><%= f.collection_select :costproject_coststatus_id_in, Coststatus.all, :id, :statuscode, include_blank: true, {}, { :multiple => true }%></td>
Thanks for the help!!
OK - this worked:
<td><%= f.collection_select :costproject_coststatus_id_in, Coststatus.all, :id, :statuscode, {:include_blank => true}, { :multiple => true }%></td>

Rails select tag with required true

I have the following select tag
<%= f.select :id, User.find(:all, :conditions => ["manager = ?", false]).collect {|u| [u.username, u.id]}, {:required => true}, {:class => "multiselect", :multiple => true} %>
I try to add :required => true to it, the view renders but :required => true doesn't work!.
Quite a bit late, but for anyone looking, checking at the reference, should go explicitly as the hash, so ruby interpreter doesn't get confused:
select(object, method, choices = nil, options = {}, html_options = {}, &block)
For this special case:
<%= f.select :id,
User.find(:all, :conditions => ["manager = ?", false]).collect {|u| [u.username, u.id]},
{:prompt => 'Select something'},
{:required => true, :class => "multiselect", :multiple => true} %>
Try this:
<%= f.select :id, User.find(:all, :conditions => ["manager = ?", false]).collect {|u| [u.username, u.id]}, {:multiple => true}, :class => "multiselect", :required => true %>

Delete a rails relationship with an :include_blank

I want to be able to select a blank object and post it so that I can clear a rails relationship. By default when you POST while selected on the :include_blank entry, nothing gets posted so it doesn't delete the old relationship. So I'm trying to add a 0 id blank item to the array.
Original:
<%= select_f f,:config_template_id, #operatingsystem.config_templates.where(:template_kind_id => f.object.template_kind_id), :id, :name, {:include_blank => true}, { :label => f.object.template_kind } %>
Mine:
<%= select_f f,:config_template_id, #operatingsystem.config_templates.where(:template_kind_id => f.object.template_kind_id).collect { |c| [c.name, c.id]}.insert(0, ['', 0]) %>
I'm getting a "wrong number of arguments (3 for 5)" error though and can't figure out what I'm missing. Any pointers? (I also can't find select_f anywhere on web, I think google ignores the _ so the search is way to open ended... For rails 3 should I be using something else?)
You've omitted the 3rd, 4th, 5th, and 6th argument you were passing into your original code block. Whatever select_f is, it's expecting at least 5 arguments. In the original you pass the following to select_f (one argument per line for clarity)
f,
:config_template_id,
#operatingsystem.config_templates.where(:template_kind_id => f.object.template_kind_id),
:id,
:name,
{:include_blank => true},
{ :label => f.object.template_kind }
In your new (broken) call you're only passing
f,
:config_template_id,
#operatingsystem.config_templates.where(:template_kind_id => f.object.template_kind_id).collect { |c| [c.name, c.id]}.insert(0, ['', 0])
Use your first method call, just replace the 3rd argument.
f,
:config_template_id,
#operatingsystem.config_templates.where(:template_kind_id => f.object.template_kind_id).collect { |c| [c.name, c.id]}.insert(0, ['', 0])
:id,
:name,
{:include_blank => true},
{ :label => f.object.template_kind }
Finally, if you don't want the :include_blank => true to be passed, but still do want the label, just pass nil or {} to the 5th argument
f,
:config_template_id,
#operatingsystem.config_templates.where(:template_kind_id => f.object.template_kind_id).collect { |c| [c.name, c.id]}.insert(0, ['', 0])
:id,
:name,
nil,
{ :label => f.object.template_kind }
And altogether on one line:
<%= select_f f, :config_template_id, #operatingsystem.config_templates.where(:template_kind_id => f.object.template_kind_id).collect { |c| [c.name, c.id]}.insert(0, ['', 0]), :id, :name, nil, { :label => f.object.template_kind } %>
I can't guarantee this works because I don't know where the API for select_f is or if you created it yourself. This should however nudge you in the right direction.

Rails - disable option in select (based on the condition)

I have select:
= f.select(:category_id, #categories, :html_options => {:class => 'select_box'}, {:disabled => true if category.id == 18})
The piece of code above obviously returns an error, but how to disable an option according by id?
Haven't tested this but in your controller could you not do
#checkvar = #category.id == 18 ? true : false
then in the view
f.select(:category_id, #categories, :html_options => {:class => 'select_box'}, {:disabled => #checkvar})
or in the model write a function to test
def disable_select
if self.id == 18
true
else
false
end
end
then in the view
f.select(:category_id, #categories, :html_options => {:class => 'select_box'}, {:disabled => #category.disable_select})
<%= f.select :status, STATUSES.map{|s| [s.titleize, s]}, { disabled: DISABLED_STATUSES.map{|s| [s.titleize, s]} %>
Ran into this recently and used the following solution:
#view
= f.select(:category_id, #filtered_categories, :html_options => {:class => 'select_box'}
#controller
#filtered_categories = Category.all.select do |category|
[logic here]
end
For select_tag, we can do:
<%= select_tag "sample", options_for_select(
[['A', 'a'], ['B', 'b'], ['C', 'c']]),
{class: 'form-control', disabled: data.present? == false ? true : false}
%>

Resources