Sort Ransack with calculated field

153 Views Asked by At

In my rails application, I use ransack to generate the sorts on the headers of my table.

This works on all columns that are included in my model, but I have a unit_price column that matches the below method of the Ingredient model which is actually a calculated field.

Is it possible to run a sort on the column header with a calculated field?

Is the only solution to save a unit_price field in the database?

def unit_price
  self.price_cents / self.quantity_by_pack
end

I try this in my model, but doesn't work

ransacker :created_at do
1

There are 1 best solutions below

0
mechnicov On

Yes, it's possible

Firstly define ransacker and ransackable_attributes such way in your model

ransacker :unit_price do |parent|
  # Functionality of your method using Arel
  parent.table[:price_cents] / parent.table[:quantity_by_pack]
end

def self.ransackable_attributes(auth_object = nil)
  # You can use something like:
  # attrs = super
  # attrs += ['unit_price']

  # But it will be deprecated so it's better to use such method:
  authorizable_ransackable_attributes
end

After that it's possible to apply it

search = Ingredient.ransack({})
search.sorts = 'unit_price asc'

search.result
# Return Active Record relation with SQL query:
# SELECT "ingredients".* FROM "ingredients"
# ORDER BY "ingredients"."price_cents" / "ingredients"."quantity_by_pack" ASC

or

search = Ingredient.ransack({})
search.sorts = 'unit_price desc'

search.result
# Return Active Record relation with SQL query:
# SELECT "ingredients".* FROM "ingredients"
# ORDER BY "ingredients"."price_cents" / "ingredients"."quantity_by_pack" DESC