Mathieu
Mathieu

Reputation: 4797

Filter on multi-select on Active Admin (Rails 3.2/postgreSQL/active admin 1.0)

I run into a problem while trying to filter on a resource on Active Admin.

Filters actually work perfectly when I apply them to standard stuff but here it's a multi-select.

Indeed in my Deals model: There is a "Deal_goal" attribute and I can choose many Deal_goal such as "acquire new users", or "generate buzz"

Here is how I input it on my active admin form:

f.input :deal_goal,
        :label      => "Deal goals",
        :as         => :select,
        :multiple   => true,
        :collection => DEAL_GOALS

To make the multi select, I serialize it on my Deal model

app/models/deal.rb

class Deal < ActiveRecord::Base
  serialize :deal_goal, Array 

I am also using staal.io advice for multi-selects (the 'chosen' gem)

What I fail to do is on my index page (list of deals), to have a filter on my Deal_goal attribute and if possible to have a multi-select here enabling me to filter on deals based on more than one type of goal (for example: filter deals with goal#1 or goal#3)

I tried both of what is below on admin/deal.rb and none worked!

filter :deal_goal,    :as => :select, :collection => DEAL_GOALS
filter :deal_goal,    :as => :multiple_select, :collection => DEAL_GOALS

Does anybody have a clue?

Upvotes: 1

Views: 5163

Answers (1)

seanlinsley
seanlinsley

Reputation: 3205

You can create a multiple select in the same way you do in your form, with multiple: true:

filter :deal_goal, as: :select, collection: DEAL_GOALS, multiple: true

UPDATE

Querying PostgreSQL arrays from Active Admin / Ransack can be done, it just takes a bit more work. First off, you should add the postgres_ext gem to your Gemfile. It gives you a nice set of query methods that you can use like this:

User.where.contains roles: ['foo']
# or:
User.where User.arel_table[:roles].contains ['foo']

The next step is to tell Ransack that these query methods (or "predicates") exist. Put this in an initializer:

# https://github.com/activerecord-hackery/ransack/issues/321
Ransack.configure do |config|
  { array_contained_within:           :contained_within,
    array_contained_within_or_equals: :contained_within_or_equals,
    array_contains:                   :contains,
    array_contains_or_equals:         :contains_or_equals,
    array_overlap:                    :overlap
  }.each do |rp, ap|
    config.add_predicate rp, arel_predicate: ap, wants_array: true
  end
end

You can confirm that Ransack is picking up on the added methods if this:

User.search(roles_contains: [3,4]).result.to_sql

Generates this SQL:

SELECT "users".* FROM "users"  WHERE ("users"."roles" @> '{"3","4"}')

Now to get these new methods working with Active Admin.

ActiveAdmin.register User do
  filter :roles_array_contains, as: :select, multiple: true, collection: ['foo', 'bar']
end

Of course, be sure to change User and roles to the model and attribute that fits your situation.

One final note. I noticed you're manually setting up serialize :attr, Array in your model. For your array to be a PostgreSQL array you have to specify array: true in the database migration. Assuming you've already done that, then this serialize call is unnecessary. In fact, it seems to break this approach for some reason, so be sure to remove it.

Upvotes: 7

Related Questions