Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom ActiveAdmin filter for Date Range

I need to create a custom ActiveAdmin filter for a Date Range which belongs to another resource. I want to filter a list of users by a date range of when they completed a survey.

I've declared a custom filter in the ActiveAdmin DSL like so:

filter :by_date_completed, label: 'By Date Completed', as: :date_range

This makes me a nice date range in active admin to restrict my users by. All good.

I haven't been able to find much documentation on how to do this but in my user model I've tried to create a ransacker to handle the filter.

ransacker :by_date_completed, {
    formatter: proc { |start_date, end_date|

        time_range = start_date..end_date
        users = User.joins(:surveys).where(surveys: { updated_at: time_range})

        users = users.map(&:id)
        users.present? ? users : nil
        }, 
    callable: proc { |parent|
    parent.table[:id]
    }
}  

But ActiveAdmin passes the date ranges to the filter one at a time and so I can't get a range to search by?

What am I meant to do in this scenario? Am I going about the whole problem in the wrong way?

like image 244
Sebastian Sibelle Avatar asked Sep 30 '14 08:09

Sebastian Sibelle


1 Answers

I think you don't need a custom ransacker for that. You can filter a cross associations.

This should work for you:

filter :surveys_updated_at, label: 'By Date Completed', as: :date_range

What you do is not, how a ransacker should work. I know it's a common google result, but it's wrong.

  1. The ransacker don't receive both dates at once in ActiveAdmin. The ransacker will called with a by_date_completed_gteq and a by_date_completed_lteq.

  2. A ransacker formatter is only to format the input value. Convert a String into a Int for example.

  3. The block / the callable proc of the ransacker needs to return a Arel / SQL string which is placed in the DB query.

A abstract ransacker example:

ransacker :foo do
  "ransacker sql code"
end

"SELECT * FROM bar WHERE 'ransacker sql code' = <input>"

Your ransack should look like this:

ransacker :by_date_completed do
  "surveys.updated_at"
end

This should end up in a query like:

"SELECT * FROM users WHERE surveys.updated_at >= START_DATE AND surveys.updated_at <= END_DATE"
like image 180
Timo Schilling Avatar answered Oct 02 '22 01:10

Timo Schilling