为什么 Rails 4.1.12 中关系的默认排序不起作用?
Why is default ordering on a relationship in Rails 4.1.12 not working?
背景
- 一个广告有很多广告车辆
- 广告车辆具有价格属性
- 我想默认按价格升序排列关系
问题
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
问题
如何让关系的默认排序语法起作用?
这些值不是从数据库中排序的,而是从您将它们传递给 create
的方式排序的:[v1, v2]
。在创建关联被视为加载后,当您调用它时,无需从数据库重新加载它(使用正确的顺序子句)。
要对它们进行排序,您可以:
- 创建前手动排序
- 重新加载整个广告对象 (
a.reload
)
- 仅重新加载关联 (
a.advertised_vehicles(true).map(&:price)
)
当然,第一个最有效,但您需要使您的排序代码与默认关系范围保持同步。所以你必须决定什么对你来说更重要。
背景
- 一个广告有很多广告车辆
- 广告车辆具有价格属性
- 我想默认按价格升序排列关系
问题
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
问题
如何让关系的默认排序语法起作用?
这些值不是从数据库中排序的,而是从您将它们传递给 create
的方式排序的:[v1, v2]
。在创建关联被视为加载后,当您调用它时,无需从数据库重新加载它(使用正确的顺序子句)。
要对它们进行排序,您可以:
- 创建前手动排序
- 重新加载整个广告对象 (
a.reload
) - 仅重新加载关联 (
a.advertised_vehicles(true).map(&:price)
)
当然,第一个最有效,但您需要使您的排序代码与默认关系范围保持同步。所以你必须决定什么对你来说更重要。