0

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.

Schema

create_table "companies", force: :cascade do |t|
 ...
 t.boolean  "female_founder"
 ...
end 

Company.rb

class Company < ApplicationRecord
 enum female_founders: {
  'Yes' => 1,
  'No' => 0
 }
end

Search.html.erb

<%= 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 'Yes' for female_founder

Search 'No' for female_founder resets search display to prompt value. The search queries correctly, it is just the display that is incorrect. Search 'No' for female_founder

2
  • Hi @Brian, Could you show the value of params[:q][: female_founder_eq] ? Commented Apr 3, 2018 at 11:43
  • 2
    Just a general question, why do you use an enum if you can use a boolean attribute directly? Commented Apr 3, 2018 at 12:00

1 Answer 1

1

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)] } %>
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for your answer. I've tried the solution you've suggested above but still no look. The display in the drop-down still reverts back to 'Any' after the search is done.
@BrianOHalloran I've looked into it a bit more and it looks like for ransack specifically the thing you'd use for :selected is @q.base[:female_founder_eq].try(:value) (where @q is whatever your query is) and I've updated my answer - can you try again?
you are amazing! Works perfectly. Thanks so much for your help!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.