在Rails的has_many关系中默认使用一个范围
假设我有以下类
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关系,这样当我为所有相关planets
询问planets
,自动应用solar_system
支持范围。 本质上,我想solar_system.planets == solar_system.planets.life_supporting
。
要求
-
我不想把
scope :life_supporting
在Planet
上default_scope where('distance_from_sun > ?', 5).order('diameter ASC')
-
我也想通过不必添加到
SolarSystem
来防止重复has_many :planets, :conditions => ['distance_from_sun > ?', 5], :order => 'diameter ASC'
目标
我想有类似的东西
has_many :planets, :with_scope => :life_supporting
编辑:工作
正如@phoet所说,使用ActiveRecord可能无法实现默认的作用域。 但是,我发现了两个潜在的解决方法。 两者都防止重复。 第一个,虽然长,保持明显的可读性和透明度,第二个是帮助types的方法谁输出是明确的。
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
另一个更清洁的解决scheme是简单地将以下方法添加到SolarSystem
def life_supporting_planets planets.life_supporting end
并在你使用solar_system.life_supporting_planets
地方使用solar_system.planets
。
既不回答这个问题,所以我只是把他们放在这里作为解决办法应该是其他人遇到这种情况。
在Rails 4中, Associations
有一个可选的scope
参数,它接受一个应用于Relation
的lambda(参考ActiveRecord :: Associations :: ClassMethods的doc)
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
在Rails 3中, where_values
解决方法有时可以通过使用where_values_hash
来处理,其中的条件是由多个where
或hash(这里不是这种情况)定义的。
has_many :planets, conditions: Planet.life_supporting.where_values_hash
我刚刚深入了解ActiveRecord,看起来好像是否可以通过has_many
的当前实现来实现。 你可以传递一个块:conditions
但是这仅限于返回条件散列,而不是任何forms的东西。
一个非常简单和透明的方法来实现你想要的(我想你要做的)是在运行时应用范围:
# foo.rb def bars super.baz end
这远远不是你所要求的,但它可能只是工作;)