为什么Rails 4.1.12中关系的默认排序不起作用?

时间:2015-07-28 09:23:59

标签: ruby-on-rails ruby ruby-on-rails-4 activerecord relationship

背景

  • 广告中有许多广告宣传的车辆
  • 广告中的车辆具有价格属性
  • 我想按默认价格升序对关系进行排序

问题

class Advert < ActiveRecord::Base
  has_many :advertised_vehicles, -> { order(price: :asc) }
end

v1 = AdvertisedVehicle.create(price: 2000)
v2 = AdvertisedVehicle.create(price: 1000)

a = Advert.create(advertised_vehicles: [v1, v2])

a.advertised_vehicles.map(&:price)
# => [2000, 1000] - fails

a.advertised_vehicles.order(price: :asc).map(&:price)
# => [1000, 2000] - works

什么有用

为了让这个工作起作用,我不得不求助于advertised_vehicles

class Advert < ActiveRecord::Base
  has_many :advertised_vehicles

  def advertised_vehicles
    super.order(price: :asc)
  end
end

我尝试过什么

class Advert < ActiveRecord::Base
  has_many :advertised_vehicles, -> { throw order(price: :asc) }
end
  • 这会抛出正确的有序关系
  • 当我删除throw时,将再次返回无序关系

版本

  • Ruby 1.9.3 p547
  • Rails 4.1.12

问题

如何获得关系的默认排序语法?

1 个答案:

答案 0 :(得分:1)

这些值不是从数据库中排序的,而是从您将它们传递给create[v1, v2]的方式排序的。在创建关联被视为已加载后,当您调用它时,无需从数据库重新加载它(具有正确的顺序子句)。

要对它们进行排序,您可以:

  • 在创建之前手动对它们进行排序
  • 重新加载整个广告对象(a.reload
  • 只重新加载关联(a.advertised_vehicles(true).map(&:price)

当然,第一个效率最高,但您需要使用默认的关系范围保持排序代码最新。所以你必须决定什么对你更重要。