问题
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...
回答1:
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.
回答2:
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
来源:https://stackoverflow.com/questions/17315392/order-model-objects-by-an-attr-accessor