Searching on an Enum Field with Ransack
Asked Answered
L

4

12

I've got a table, 'jobs' with a enum field 'status'. status has the following enum set:

enum status: [ :draft, :active, :archived ]

using ransack, how do I filter the table for, say, all active records?

Letty answered 16/5, 2016 at 15:41 Comment(1)
Please post what you have tried so far.Stocky
S
27

You can declare own ransacker in model like this:

ransacker :status, formatter: proc {|v| statuses[v]} do |parent|
  parent.table[:status]
end

Then You can use default ransack syntax _eq to check equality like this:

Model.ransack(status_eq: 'active').result

Edit: If column name doesn't change you can skip block of code:

ransacker :status, formatter: proc {|v| statuses[v]}
Sheepshanks answered 16/5, 2016 at 19:45 Comment(3)
Thanks. that works, but it seems like i might as well just use the param value and do a regular search. the code reads a bit better / simple that way. Adding a filter in ActiveAdmin worked without creating a ransacker, even though they use Ransack for their filtering. It seems odd it didn't work on the front end as easily.Letty
@Letty Yeap, you can use just simple scope. It should work fine :) But problem appears when You can't skip using ransack. Without code mentioned above, it's going to always cast parameter active to integer .to_i so You will get always 0 instead of proper value.Sheepshanks
after googling and reading your comments, you may combine, but there could be issues when using arel.group, Model.active.ransack(params_for_others) works. I'll write an answerFujimoto
M
9

This is something I use in my views for enums and ransack:

<%= f.select :status_eq, Model.statuses.to_a.map { |w| [w[0].humanize, w[1]] },
                         {:include_blank => true} %>
Maeganmaelstrom answered 16/6, 2016 at 12:46 Comment(2)
So it appears then that you must pass the integer value of attribute to the q hash, since ransack will not do the enum conversation for you.Man
Any idea how to make it as radio_buttons?Indispose
R
1

Below works fine for all cases :draft, 'draft', 0, '0' in model

ransacker :status do |parent|
  parent.table[:status]
end
Reluct answered 12/10, 2021 at 9:57 Comment(0)
F
0

ransacker in accepted answer of @qarol works but since OP is looking for a cleaner solution, you may also opt to combine enum defined scopes with ransack like the following:

Model.active.ransack(params_for_others).result
Model.not_active.ransack(params_for_others).result

These works properly.

You may check with: puts Model.active.ransack(onboarded_eq: true).result.to_sql will print:

SELECT "model".* FROM "models" WHERE "models"."status" = 1 AND "users"."onboarded" = TRUE

however, beware of some issues when combining ransack + arel, e.g. GroupingError

PG::GroupingError: ERROR:  column \"other_model.id\" must appear in the GROUP BY clause or be used in an aggregate function
Fujimoto answered 13/12, 2023 at 12:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.