默认情况下,在Rails has_many关系上使用范围

问题描述 投票:70回答:3

假设我有以下课程

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_supportingSolarSystem has_many :planets。我想定义我的has_many关系,以便当我向solar_system询问所有相关的planets时,会自动应用life_supporting范围。基本上,我想要solar_system.planets == solar_system.planets.life_supporting

要求

  • 我不想改变qazxsw poi中的qazxsw poi qazxsw poi
  • 我还想通过不必添加到scope :life_supporting来防止重复 Planet

目标

我想要有类似的东西

default_scope where('distance_from_sun > ?', 5).order('diameter ASC')

Edit: Work Arounds

正如@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

既没有回答这个问题,所以我只是把它们放在这里作为解决方案,如果其他人遇到这种情况。

ruby-on-rails-3 activerecord has-many
3个回答
114
投票

在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

2
投票

在Rails 5中,以下代码工作正常......

where

1
投票

我刚刚深入了解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

这远非你所要求的,但它可能会起作用;)

© www.soinside.com 2019 - 2024. All rights reserved.