justinbach
justinbach

Reputation: 1955

ActiveAdmin, polymorphic associations, and custom filters

Rails 3.1, ActiveAdmin 0.3.4.

My question is somewhat similar to this one but different enough in terms of data modeling that I think it warrants its own response. Models:

class CheckoutRequest < ActiveRecord::Base  
  has_one :request_common_data, :as => :requestable, :dependent => :destroy
end

class RequestCommonData < ActiveRecord::Base
  belongs_to :requestable, :polymorphic => true
end

The RequestCommonData model has a completed field (boolean) that I'd like to be able to filter in ActiveAdmin's CheckoutRequest index page. I've tried a few different approaches to no avail, including the following:

filter :completed, :collection => proc { CheckoutRequest.all.map { |cr| cr.request_common_data.completed }.uniq }

which results in no filter being displayed. Adding :as => :select to the line, as follows:

filter :completed, :as => :select, :collection => proc { CheckoutRequest.all.map { |cr| cr.request_common_data.completed }.uniq }

results in the following MetaSearch error message:

undefined method `completed_eq' for #<MetaSearch::Searches::CheckoutRequest:0x007fa4d8faa558>

That same proc returns [true, false] in the console.

Any suggestions would be quite welcome. Thanks!

Upvotes: 2

Views: 3064

Answers (1)

glampr
glampr

Reputation: 379

From the meta_search gem page you can see that for boolean values the 'Wheres' are:

  • is_true - Is true. Useful for a checkbox like “only show admin users”.
  • is_false - The complement of is_true.

so what you need is to change the generate input name from 'completed_eq' to be 'completed_is_true' or 'completed_is_false'.

The only way I have found this possible to do is with Javascript, since by looking at the Active Admin code, the 'Wheres' are hardcoded for each data type.

I would usually have a line like this in my activeadmin.js file (using jQuery)

$('#q_completed_eq').attr('name', 'q[completed_is_true]');

or

$('#q_completed_eq').attr('name', 'q[completed_is_false]');

Terrible and ugly hack but have found no other solution myself.

Be careful to enable this only in the pages you want.

--- NEW FOR VERSION 0.4.2 and newer ---

Now Active Admin uses separate modules for each :as => ... option in the filters. So for example you can place the code below inside an initializer file

module ActiveAdmin
  module Inputs
    class FilterCustomBooleanInput < ::Formtastic::Inputs::SelectInput
      include FilterBase

      def input_name
        "#{@method}_is_true"
      end

      def input_options
        super.merge(:include_blank => I18n.t('active_admin.any'))
      end

      def method
        super.to_s.sub(/_id$/,'').to_sym
      end

      def extra_input_html_options
        {}
      end
    end
  end
end

and the use

:as => :custom_boolean

where you specify your filter.

Upvotes: 2

Related Questions