I have a Class Company with a boolean attribute of female_founder. The company either has a female_founder (true) or not (false).
I have created a search filter using the ransack gem to query whether a company is female-founded or not. When I query 'true' searches, the enum value saves and displays fine, but when I search for the 'false' value, the display resets to the prompt value I have given it.
Why is this? And how can I fix it? I want the display to show whichever value I have selected.
create_table "companies", force: :cascade do |t|
...
t.boolean "female_founder"
...
end
class Company < ApplicationRecord
enum female_founders: {
'Yes' => 1,
'No' => 0
}
end
<%= f.label :female_founder_eq, 'Female Founder' %>
<%= f.select :female_founder_eq, Company.female_founders.to_a, {prompt: "Any"} %>
Search 'Yes' for female_founder returns correct display
Search 'No' for female_founder resets search display to prompt value.
The search queries correctly, it is just the display that is incorrect.
Here's where Rails determines whether to add the prompt, in rails/actionview/lib/action_view/helpers/tags/base.rb:
def add_options(option_tags, options, value = nil)
if options[:include_blank]
option_tags = tag_builder.content_tag_string("option", options[:include_blank].kind_of?(String) ? options[:include_blank] : nil, value: "") + "\n" + option_tags
end
if value.blank? && options[:prompt]
option_tags = tag_builder.content_tag_string("option", prompt_text(options[:prompt]), value: "") + "\n" + option_tags
end
option_tags
end
When Rails is building its select tag, it's determining whether to include a prompt by using blank?
, which can't distinguish whether it's nil
or false
; because @company.female_founder
is false
, and false
is blank?
, it will assume no value was given and add the prompt. (This may or may not be intentional on their part.)
Now, the value
here is the tag's selected value, which can be overriden if the :selected
option is defined, so if :selected
is manually set to your No value of 0
, then it should suppress the prompt as expected (because 0
is not blank?
). Here's a kludge that appears to work for me for a regular form:
# 1 if true - show 'Yes', 0 if false - show 'No', nil if nil - show 'Any'
<%= f.select :female_founder, Company.female_founders.to_a, { prompt: "Any", selected: { true => 1, false => 0 }[@company.female_founder] } %>
For ransack it'll need to look something like this:
<%= f.select :female_founder_eq, Company.female_founders.to_a, {prompt: "Any", selected: { true => 1, false => 0 }[@q.base[:female_founder_eq].try(:value)] } %>