Order model objects by an attr_accessor

跟風遠走 提交于 2019-12-10 23:27:17

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!