假设我有以下课程
class SolarSystem < ActiveRecord::Base
has_many :planets
end
class Planet < ActiveRecord::Base
scope :life_supporting, where('distance_from_sun > ?', 5).order('diameter ASC')
end
Planet
有一个范围life_supporting
和SolarSystem
has_many :planets
。我想定义我的has_many关系,以便当我向solar_system
询问所有相关的planets
时,会自动应用life_supporting
范围。基本上,我想要solar_system.planets == solar_system.planets.life_supporting
。
scope :life_supporting
来防止重复
Planet
我想要有类似的东西
default_scope where('distance_from_sun > ?', 5).order('diameter ASC')
正如@phoet所说,使用ActiveRecord可能无法实现默认范围。但是,我发现了两个潜在的工作。两者都可以防止重复。第一个是长期保持明显的可读性和透明度,第二个是助手类型方法,其输出是显式的。
SolarSystem
另一个更清洁的解决方案是简单地将以下方法添加到has_many :planets, :conditions => ['distance_from_sun > ?', 5], :order => 'diameter ASC'
has_many :planets, :with_scope => :life_supporting
并且无论你在哪里使用class SolarSystem < ActiveRecord::Base
has_many :planets, :conditions => Planet.life_supporting.where_values,
:order => Planet.life_supporting.order_values
end
class Planet < ActiveRecord::Base
scope :life_supporting, where('distance_from_sun > ?', 5).order('diameter ASC')
end
,都要使用SolarSystem
。
既没有回答这个问题,所以我只是把它们放在这里作为解决方案,如果其他人遇到这种情况。
在Rails 4中,def life_supporting_planets
planets.life_supporting
end
有一个可选的solar_system.life_supporting_planets
参数,它接受一个应用于solar_system.planets
的lambda(参见Associations
的文档)
scope
在Rails 3中,有时可以通过使用Relation
来改进ActiveRecord::Associations::ClassMethods变通方法,class SolarSystem < ActiveRecord::Base
has_many :planets, -> { life_supporting }
end
class Planet < ActiveRecord::Base
scope :life_supporting, -> { where('distance_from_sun > ?', 5).order('diameter ASC') }
end
处理更好的范围,其中条件由多个where_values
或哈希定义(这里不是这种情况)。
where_values_hash
在Rails 5中,以下代码工作正常......
where
我刚刚深入了解ActiveRecord,看起来不像是否可以通过has_many :planets, conditions: Planet.life_supporting.where_values_hash
的当前实现来实现。你可以传递一个块到 class Order
scope :paid, -> { where status: %w[paid refunded] }
end
class Store
has_many :paid_orders, -> { paid }, class_name: 'Order'
end
,但这仅限于返回条件的哈希,而不是任何类型的东西。
一个非常简单透明的方法来实现你想要的东西(我认为你想要做的)是在运行时应用范围:
has_many
这远非你所要求的,但它可能会起作用;)