6

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?

1 Answer 1

9

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"
2
  • Thanks Timo! Makes sense. Commented Aug 19, 2015 at 4:38
  • I ended up having to go with ransacker(:name, type: :date) { Arel.sql('date(timestamp_column)') } to get as: :date_range to work with a timestamp column. Commented Feb 2, 2022 at 22:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.