[ruby-on-rails-3] 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_supportingSolarSystem has_many :planets. 내가 물어 때 그래서 난 내 has_many 관계를 정의하고자하는 solar_system모든 관련 위해 planetslife_supporting범위가 자동으로 적용됩니다. 기본적으로 solar_system.planets == solar_system.planets.life_supporting.

요구 사항

  • 나는 할 수 없습니다 변경할 scope :life_supportingPlanet

    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를 사용하여 기본 범위를 달성하지 못할 수도 있습니다. 그러나 두 가지 잠재적 인 해결 방법을 찾았습니다. 둘 다 중복을 방지합니다. 첫 번째는 길지만 분명한 가독성과 투명성을 유지하고 두 번째는 출력이 명시적인 도우미 유형 메서드입니다.

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

def life_supporting_planets
  planets.life_supporting
end

그리고 solar_system.life_supporting_planets어디에서나 사용할 수 있습니다 solar_system.planets.

둘 다 질문에 대답하지 않으므로 다른 사람이 이러한 상황에 직면 할 경우 해결 방법으로 여기에 넣었습니다.



답변

Rails 4 Associations에는에 scope적용되는 람다를 허용 하는 선택적 매개 변수가 있습니다 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

Rails 3 에서는 조건이 다중 또는 해시 (여기에서는 해당되지 않음) 로 정의되는 더 나은 범위를 처리 하는 where_values방법을 사용하여 해결 방법을 개선 할 수 있습니다 .where_values_hashwhere

has_many :planets, conditions: Planet.life_supporting.where_values_hash


답변

Rails 5에서는 다음 코드가 잘 작동합니다.

  class Order 
    scope :paid, -> { where status: %w[paid refunded] }
  end

  class Store 
    has_many :paid_orders, -> { paid }, class_name: 'Order'
  end


답변

방금 ActiveRecord에 대해 자세히 살펴 보았고 현재 .NET 구현으로 이것이 달성 될 수있는 것처럼 보이지 않습니다 has_many. 당신은 블록을 전달할 수 :conditions있지만 이것은 어떤 종류의 영역 물건이 아닌 조건의 해시를 반환하는 것으로 제한됩니다.

원하는 것을 달성하는 정말 간단하고 투명한 방법 (내가하려는 작업)은 런타임에 범위를 적용하는 것입니다.

  # foo.rb
  def bars
    super.baz
  end

이것은 당신이 요구하는 것과는 거리가 멀지 만 작동 할 수도 있습니다.)


답변