Skip to content

How to yes/no/any on a scope taking a boolean argument? #1661

@kalsan

Description

@kalsan

I'm trying to figure out the most elegant way to achieve the following with ransack: Imagine a Rails model User that has_many :licenses of type License. Now, I'd like to add a filter "Has at least one license" to a filter form for users where I can choose between:

  • doesn't matter ("any"), filter is not active
  • "Yes"
  • "No"

Seemed obvious at first, but I've just spend hours doing this in many wrong ways.

Here's what I've tried:

First attempt: Two scopes

I've implemented scopes with_licenses and without_licenses. I was unable to combine those into a single select input in the filter form.

Second attempt: Custom ransacker

I've implemented a custom ransacker ransacker :licenses_exist and called the select field :licenses_exist_true or :licenses_exist. In both cases, the form attempts to call .licenses_exist_true or .licenses_exist on ransacker's Search object in the value method (which of cause fails). I am getting the feeling that combinding a custom ransacker with a select field does not work with current versions of ransack, very much contrary to the documentation, which states that it should work: https://activerecord-hackery.github.io/ransack/going-further/ransackers/#testing-for-existence

Did I find a bug / am I misunderstanding something?

Third to sixth attempts: scope with a single argument

Something of the sorts scope licenses_exist, lambda {|value| ... }

Attempt 3 was to pass f.select(:licenses_exist, [['', nil], [_('Yes'), '1'], [_('No'), '0']]), where values like 1, "1", true, "true", and even "yes" were eaten by ransack and no argument was passed to the lambda.

Attempt 4 was to make the lambda's argument optional, but then I could not distinguish between the case "any" and "no".

Attempt 5 was to set config.sanitize_custom_scope_booleans = false in an initializer, which broke all of my other scopes, of course.

And the final attempt, number 6, is that I have f.select(:licenses_exist, [['', nil], [_('Yes'), 'y'], [_('No'), 'n']]) since those are not eaten by Ransack.

Struggle is real. This can't be that hard, can it? After all, my second attempt is even documented on the documentation. What am I doing wrong? How to do this for real?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions