Question

I thought that attr_accessor has the same behavior as the other when I have to sort a list of objects, but it seems that is different:

  dataRecords = MyData.where("day = ?", Time.now.yesterday.strftime("%Y%m%d").to_i)
  dataRecords.each do |data|
    data.accessor_var = func(data.x, data.y)
  end
  @sortedData = dataRecords.order('accessor_var DESC')

but @sortedData is not being sorted...

Was it helpful?

Solution

You need to keep in mind that when you apply a scope or order to an ActiveRecord::Relation the data is reloaded from the table. This means that when you loop through them and change an attribute, unless you save the result the changes will not be available to the next scope call.

You can use sort_by instead which will work on the objects in memory rather than the database.

Option 1: Save as you loop (probably not much use with an accessor!)

dataRecords = MyData.where("day = ?", Time.now.yesterday.strftime("%Y%m%d").to_i)
dataRecords.each do |data|
  data.accessor_var = func(data.x, data.y)
  data.save
end
@sortedData = dataRecords.order('accessor_var DESC') # Reload from table will include the saved values.

Option 2: sort_by

dataRecords = MyData.where("day = ?", Time.now.yesterday.strftime("%Y%m%d").to_i)
dataRecords.each do |data|
  data.accessor_var = func(data.x, data.y)
end
@sortedData = dataRecords.sort_by{|data| data.accessor_var}

Also, toro2k has some nice optimisation for your sorting once you understand the situation.

OTHER TIPS

It doesn't work because accessor_var is not a column in the database. You can use the method sort_by:

dataRecords.each { ... }
@sortedData = dataRecords.sort_by(&:accessor_var).reverse

Or, to save an interation over dataRecords:

@sortedData = dataRecords.sort_by { |data| data.accessor_var = func(data.x, data.y) }.reverse
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top