Delete a rails relationship with an :include_blank - ruby-on-rails

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.

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

Neo4jrb: a way to query for the model_class while doing collection_select

Is there a way to have a couple generic lines of code that can return results from the correct model_class based on the the model definition, and not on the lines of code?
Right now, I'm using a generator to create:
<%= f.collection_select(:semanticZoomOut, Class.all.sort { |a,b| a.name <=> b.name },
:id, :name, options = {
:prompt => "Please Select an Item",
:selected => #instance.semanticZoomOut.map(&:id)
}, html_options = {:multiple => true, :class=>"search"}) %>
Where "Class" has to be manually changed for each _form.html.erb.
Preferably, I'd like to generate something like this:
<%= f.collection_select(:semanticZoomOut, #instance.semanticZoomOut.class.all.sort { |a,b| a.name <=> b.name },
:id, :name, options = {
:prompt => "Please Select an Item",
:selected => #instance.semanticZoomOut.pluck(id)
},
html_options = {:multiple => true, :class=>"search"}) %>
How about this?
clazz = #instance.class.associations[:semanticZoomOut].model_class.to_s.constantize
clazz.all.sort_by(&:name)
Or if you want to let Cypher do the work:
clazz.order(:name)

rails form select multiple gives empty first value

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

Use hash as source for collection_check_boxes

I have the following hash:
FIELD_LIST = {
-1 => 'User',
-2 => 'Duration',
-3 => 'Price',
-4 => 'Invoiced'
}
I want to use this with a collection_check_boxes.
In the manual it says:
The :value_method and :text_method parameters are methods to be called on each member of collection.
So I tried this:
= f.collection_check_boxes TimesheetReport::FIELD_LIST, [0], [1], :input_html => { :class => 'checkbox' }
But that gives me an error.
How is it possible to use a hash as input to generate the checkboxes?
Actually, it is possible. A Hash is technically a collection of objects. You can do something like this:
= f.collection_check_boxes :field_name, TimesheetReport::FIELD_LIST, :first, :last, :input_html => { :class => 'checkbox' }
Replace :field_name with the actual name of your attribute where you want to store this data. It should work.

Where to put a class on the f.select in Ruby?

I am trying to apply a class to a select form element that is built with Ruby.
Here is the f.select:
<%= f.select :within, ["5km", "50km", "100km", "250km", "500km", "1000km"], { :include_blank => 'Anywhere', :selected => (params[:listing][:within] unless params[:listing].nil? || !params[:listing].has_key?(:within)) } %>
Where does the class go? My class is:
:class => 'input-medium'
Thanks!
See the documentation, specifically the html_options argument.
Add yet another argument onto the end of what you've posted in your question with:
{ class: "input-medium" }
Altogether that's
<%= f.select :within, ["5km", "50km", "100km", "250km", "500km", "1000km"], { :include_blank => 'Anywhere', :selected => (params[:listing][:within] unless params[:listing].nil? || !params[:listing].has_key?(:within)) }, { class: "input-medium" } %>

Resources