using include_blank in f.select but not working - ruby-on-rails

I want to use dropdown to list all my projects and the first option is blank.
but when I add :include_blank => true, it doesn't work.
just like that:
<%= f.select(:project_id, :include_blank => true) do %>
<% #projects.each do |p| %>
<%= content_tag(:option, p.name, value: p.id) %>
<% end -%>
<% end -%>
but if I use
<%= f.select(:title, %w{ Male Female }, :include_blank => true) %>
It works exactly!
I don't know how to revise the first code to make the blank appear.
Thanks!

Use like this:
<%= f.select :category_id, nil, :include_blank => true %>
In the documention API LINK
select(object, method, choices = nil, options = {}, html_options = {}, &block)

I think the problem is the <%= content_tag … %>. Try this:
<%= f.select(:project_id, :include_blank => true) do
#projects.each do |p|
content_tag(:option, p.name, value: p.id)
end
end %>
(ie. just a single ERB output embedding tag)
Update: looking over this again, you are not really customising the way the options are generated, do you really need the block?
<%= f.select(:project_id, #projects.collect { |p| [p.name, p.id] }, :include_blank => true) %>

U can do this:
<%= f.select(:project, :id, #projects.collect {|p| [ p.name, p.id ] }, {:include_blank => true}) %>
Or
<%= f.select(:project_id, #projects.collect {|p| [ p.name, p.id ] }, {:include_blank => true}) %>
Or you can use prompt:
<%= f.select(:project, :id, #projects.collect {|p| [ p.name, p.id ] }, {:prompt => 'select project'}) %>

Related

"Undefined" placeholder on f.select in form

I have a form
<%= form_for #user, url: contact_path do |form| %>
<%= form.select(:email, User.all.map(&:email), {}, { class: 'my-form' }) %>
<% end %>
which works well but has placeholder "Undefined" in start position.
I tried to get rid of that with
<%= form.select(:email, User.all.map(&:email), {placeholder: "Select email"}, { class: 'my-form' }) %>
or
<%= form.select(:email, User.all.map(&:email), {prompt: "Select email"}, { class: 'my-form' }) %>
but still same. Any ideas?
<%= form.select :email, options_for_select(User.all.map(&:email)), include_blank: "whatever your prompt says" , class: 'my-form' %>
Experienced same issues today and this is what I did for one of our projects recently.
<%= f.select :category, options_for_select(Category.all.collect { |c| [c.name, c.id] }), { include_blank: 'Select category' }, { class: 'custom-select' } %>
Try changing the values according to your values.
This is how you add class and placeholder in a form.select element in Rails.

Add multiple suggestion values in select ruby on rails

<%= f.select :id, lists.collect{ |p| [p.name, p.id] } << "add product", { prompt: t("select product") }, { :class => "selectpicker" } %>
The problem is that "add product" is being added on the last index but I want it on the second index.
You can use insert and pass the index you want to insert the data in:
Tweaking a bit the code:
<%= f.select :id, lists.map { |p| [p.name, p.id] }.insert(1, 'add product'), { prompt: t('select product') }, { class: 'selectpicker' } %>

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

Set multi select for select tag

i have a select tag which i am generating by looping the records and creating options manually. Here is the code:
<%= f.select (:book_id_eq_any) do %>
<%= content_tag(:option, "Choose your option", value: "", disabled: '', selected: '') %>
<% #books.each do |book| %>
<%= content_tag(:option, book.book_title, value: book.id) %>
<% end %>
<% end %>
When i add {multiple: true}, it does not work. Can anyone give me hint about it. Thanks
Just use the built-in select form helper:
<%= f.collection_select :book_id_eq_any, #books, :id, :book_title, { include_blank: "Choose your option" }, { multiple: true } %>

Refactor ugly if/else statement in Rails View

I have this nasty if/else statement in a rails view:
<% if question.field_type == "text_area" %>
<%= f.text_area :content, :class=>"form-control question-field", :data => {:question => question.id, :filter=> #filter}, :value=> question.answer(#assessment).try(:content) %>
<% elsif question.field_type == "date" %>
<%= f.date_select :content, { :order => [:year, :month, :day], :prompt => { :day => 'day', :month => 'month', :year=> "year" }, :end_year=> Date.today.year, :start_year => Date.today.year - 2 }, {:class => "question-field", :data => {:question => question.id, :filter=> #filter}, :value=> question.answer(#assessment).try(:content)} %>
<% elsif question.field_type == "text_field" %>
<%= f.text_field :content, :class=>"form-control question-field", :value=> question.answer(#assessment).try(:content), :data => {:question => question.id, :filter=> #filter} %>
<% elsif question.field_type == "dropdown" %>
<%= f.select :content, options_for_select(question.options), { :prompt => "Choose One..." }, :class=>"form-control question-field", :value=> question.answer(#assessment).try(:content), :data => {:question => question.id, :filter=> #filter} %>
<% elsif question.field_type == "number" %>
<%= f.select :content, options_for_select(1..10), {:include_blank=> true}, :class=>"form-control question-field", :value=> question.answer(#assessment).try(:content), :data => {:question => question.id, :filter=> #filter} %>
<% elsif question.field_type == "percentage" %>
<h2>100%</h2>
<%= f.range_field :content, :value=> get_percentage(question), :class=> "question-field percentage", :data => {:question => question.id, :filter=> #filter}, :step => 25, :in => 0..100 %>
<% end %>
Is there a good way to refactor this to make it nicer? This piece of code is in every field:
:class=>"form-control question-field", :value=> question.answer(#assessment).try(:content), :data => {:question => question.id, :filter=> #filter}
Do I refactor into a helper method or a partial?
Sometimes templates are just messy and you can only clean up detail. Refactoring into a parameterized partial will help. For goodness sake, use a case. And consider switching to HAML. It eliminates a lot of the visual clutter.
<%= render 'question_field', f: f, type: question.field_type %>
Then in _question_field.erb,
<%= case type %>
<% when 'text_area' %>
<% f.text_area :content, class: 'form-control question-field', %>
<% data: { question: question.id, filter: #filter }, %>
<% value: question.answer(#assessment).try(:content) %>
<% when ... %>
<% end %>
Note common industrial practice is to pick a max line length and stick to it: 100 and 120 are pretty common. Also, use the new symbol key notation for hashes. The old hook-and-arrow is too noisy.
In HAML:
= case type
- when 'text_area'
- f.text_area :content, class: 'form-control question-field',
data: { question: question.id, filter: #filter },
value: question.answer(#assessment).try(:content)
- when ...
I would get rid of if's and when's altogether by creating seperate partial for every possibility, then you just end up with:
<%= render question.field_type, locals: {question: question} %>
Or to make it even cleaner for view make helper method and call only
<%= question_field(question) %>
and this method would look little bit like
def question_field(question)
return render question.field_type, locals: {question: question}
# raise when no partial found, or do something elese
end

Resources