gary1410
gary1410

Reputation: 307

Active Admin custom filter with ransacker

I'm trying to write a custom method on an ActiveAdmin Users model. It's my understanding that I have to use ransacker for this.

What I'd like happen is have a select with the following that shows up in the UI drop downs like this:

Aug 2010-Aug 2011
Aug 2011-Aug 2012
Aug 2012-Aug 2013
Aug 2013-Aug 2014
Aug 2014-Aug 2015
Aug 2015-Aug 2016

Here are my tables where I need to grab the information from.

Users
------
id (int)

school_participants
-------------------
user_id (int)
start_date (datetime)

SchoolParticipant belongs to a user, a user has many school_participants.

I initially tried doing something like this in ActiveAdmin filter

  filter :participant_schools_start_date, :label => "School Year", :as => :select, :collection => [['2010', '2010-08-15'], ['2011', '2013-08-15']]

Just to see what we get in the forms, but I need a way to pass a range in the select fields, but apparently, you can only pass one value at a time. The first element (2010) in this array gets shown in the UI and the second element (2010-08-15) is what gets passed as the value.

Basically I'm trying to query between these ranges

**ON Selection in a drop down**                   **Query I want**
         Aug 2010-Aug 2012 a query between   2010-08-15 to 2011-08-15
         Aug 2011-Aug 2012                   2011-08-15 to 2012-08-15
         Aug 2012-Aug 2013                   2012-08-15 to 2013-08-15
         Aug 2013-Aug 2014                   2013-08-15 to 2014-08-15
         Aug 2014-Aug 2015                   2014-08-15 to 2015-08-15
         Aug 2015-Aug 2016                   2015-08-15 to 2016-08-15 

I tried to play with procs and lambdas using some resources I found like this one

http://nikhgupta.com/code/activeadmin/custom-filters-using-ransacker-in-activeadmin-interfaces

and

http://cavewall.jaguardesignstudio.com/2014/05/01/activeadmin-filters-with-ransack/

Any thought? Not sure how to make it work.

Upvotes: 4

Views: 3346

Answers (1)

Jacob Kjeldahl
Jacob Kjeldahl

Reputation: 13

A solution would be to provide a value in the filter which should be converted to the date range:

filter :school_participants_schoolyear_in, as: :select, collection: %w[Aug 2013-Aug 2014 Aug 2014-Aug 2015 Aug 2015-Aug 2016 Aug 2016-Aug 2017]

And then convert that value in the ransacker (defined on the school participant model):

ransacker :schoolyear,
        formatter: proc { |range_string|
          dates = range_string.split('-').map{|d| (Date.parse(d) + 15.days).to_date}
          date_range = dates.first...dates.last
          results = SchoolParticipants.where(start_date: date_range).pluck(:id)
          results.present? ? results : nil
        }, splat_params: true do |parent|
  parent.table[:id]
end

It will result in an extra query to find the ids of the SchoolParticipants so it can insert where school_participants.id IN ([all ids of relevant school participants]) in every scope query.

Upvotes: 1

Related Questions