0

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?

Tolga
  • 1,307
  • 3
  • 16
  • 31

3 Answers3

1

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)
widjajayd
  • 6,090
  • 4
  • 30
  • 41
  • I have tried your suggested solution but there is a problem with the pagination.. I receive following error for controller: undefined method `paginate' for # – Tolga Sep 22 '17 at 07:02
1

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.

Mohanraj
  • 4,056
  • 2
  • 22
  • 24
  • Thanks for your explanation. I was looking for how I can sort based on a calculated field and from your clear explanation I can understand it can be achieved with only sort by function. However in this case, .paginate on my controller is giving an error. Can you please elaborate how I can achieve both sort_by custom field and .paginate work? – Tolga Sep 22 '17 at 07:11
  • 1
    Please check this qsn and answer https://stackoverflow.com/questions/4352895/ruby-on-rails-will-paginate-an-array. Which explains how can we use paginate on custom ruby array. – Mohanraj Sep 22 '17 at 07:45
1

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.

Deepesh
  • 6,138
  • 1
  • 24
  • 41
  • Thanks for your answer. Actually there seems no problem with (Date.today - self.created_at).to_i on the other hand I understand your suggested solution for days calculation seems more appropriate. Regarding to the order, yes for this particular calculation I can even order directly based on the created_at column. However apart from the question at hand, I am very curious how I can order based on a calculated field which I define in the model. – Tolga Sep 22 '17 at 07:05
  • Which gem are you using for pagination? – Deepesh Sep 22 '17 at 07:08
  • gem 'will_paginate' – Tolga Sep 22 '17 at 07:17
  • 1
    @Tolga I have updated the answer for your pagination issue. – Deepesh Sep 22 '17 at 07:19
  • Thanks dor your explanations Deep. – Tolga Sep 22 '17 at 08:22