Reputation: 1357
I have a calculated field in my model as follows.
class Products < ApplicationRecord
attr_reader :days
def days
(Date.today - self.created_at).to_i
end
end
When I try to sort it with, I receive an error.
@products = Product.all.order("days").paginate(:page => params[:page], :per_page => 15)
Error:
PG::UndefinedColumn: ERROR: column "days" does not exist
I will appreciate if anyone can show me how to sort based on a calculated field?
Upvotes: 1
Views: 713
Reputation: 6398
I am not sure how you are running this piece of code:
(Date.today - self.created_at).to_i
Because it expects a numeric value with the -
sign. I was able to do it like this:
((Time.zone.now - self.created_at) / 1.day).to_i
But the main point is I think you want to order the records by created_at
date. So by default it is ascending and you want to display the records which has been recently created first so you can do it like this directly:
Product.all.order(:created_at)
and if you want it in descending order then you can do it like this:
Product.all.order(created_at: :desc)
Still if you need to sort
it by an attr_reader
the other answers show how you can do it. Just the issue will be that the pagination
works on ActiveRecord::Collection
rather than array so for will_paginate
you may refer here:
Ruby on Rails will_paginate an array
Hope this helps.
Upvotes: 1
Reputation: 4200
Rails order clause parameter columb should be exist in the table, does not support for user defined custom attribute in the model. So, you have to use the ruby sort_by method for custom defined attributes like below,
Product.all.sort_by(&:days)
And also you have to change your method to like below,
def days
DateTime.now.to_i - self.created_at.to_i
end
It will just work but this is not a best practice to sort the records based on custom user defined custom attribute. So, you have to move this logic to sql query itself like below,
Product.all.order("now() - created_at")
It works on postgres, not sure about mysql, please check alternate in mysql if not working.
Upvotes: 2
Reputation: 6253
the problem for your code above is attr_reader :days, meanwhile days you declared as method not variable
here is my idea for your problem
in your model
class Products < ApplicationRecord
def total_days
(Date.today - self.created_at).to_i
end
def self.sorted_by_days
Product.all.sort_by(&:total_days).reverse
# just delete .reverse incase you want ascending
# I put reverse in case you want to sort descending
end
end
in your controller
@products = Product.sorted_by_days.paginate(:page => params[:page], :per_page => 15)
Upvotes: 1