本文介绍了默认在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

行星的范围为 life_supporting SolarSystem has_many:planets 。我想定义我的has_many关系,以便当我向所有关联的行星询问 solar_system 时, life_supporting 范围会自动应用。本质上,我想要 solar_system.planets == solar_system.planets.life_supporting

Planet has a scope life_supporting and SolarSystem has_many :planets. I would like to define my has_many relationship so that when I ask a solar_system for all associated planets, the life_supporting scope is automatically applied. Essentially, I would like solar_system.planets == solar_system.planets.life_supporting.


  • 我不是要更改 scope:life_supporting 行星

default_scope其​​中('distance_from_sun>?',5).order (直径ASC)

我也想通过不必添加到 SolarSystem

I'd also like to prevent duplication by not having to add to SolarSystem

has_many:planets,:conditions => [’distance_from_sun> ?’,5],:order => '直径ASC'

我想拥有类似的东西

has_many:planets,:with_scope => :life_supporting

如@phoet所说,可能使用ActiveRecord无法实现默认范围。但是,我发现了两个潜在的解决方法。两者都防止重复。第一个虽然很长,但仍保持明显的可读性和透明性,第二个是输出清晰的辅助类型方法。

As @phoet said, it may not be possible to achieve a default scope using ActiveRecord. However, I have found two potential work arounds. Both prevent duplication. The first one, while long, maintains obvious readability and transparency, and the second one is a helper type method who's output is explicit.

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

Another solution which is a lot cleaner is to simply add the following method to SolarSystem

def life_supporting_planets
  planets.life_supporting
end

并在任何要使用 solar_system.planets solar_system.life_supporting_planets >。

and to use solar_system.life_supporting_planets wherever you'd use solar_system.planets.

都没有回答这个问题,所以我只是把它们放在这里,以防其他任何人遇到这种情况。

Neither answers the question so I just put them here as work arounds should anyone else encounter this situation.

推荐答案

在Rails 4中,关联有一个可选的 scope 参数,该参数接受应用于 Relation 的lambda(请参见)

In Rails 4, Associations have an optional scope parameter that accepts a lambda that is applied to the Relation (cf. the doc for 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

在Rails 3中,有时可以通过使用 where_values_hash 处理更好的作用域来改进 where_values 解决方法条件由多个其中或哈希(此处不是这种情况)定义。

In Rails 3, the where_values workaround can sometimes be improved by using where_values_hash that handles better scopes where conditions are defined by multiple where or by a hash (not the case here).

has_many :planets, conditions: Planet.life_supporting.where_values_hash

这篇关于默认在Rails has_many关系上使用范围的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-17 20:46