ruby-on-rails - belongs - rails has_many api



범위가있는 리팩토링 has_many (1)

저는 초보자이고 방금 전문가에게 제 코드를 보여주었습니다. has_many 를 사용하여 제 변수를 필터링해서는 has_many scopes 를 지정해야한다고 말했습니다.

세 가지 모델이 있습니다 : 사용자, 제품 및 소유권.

그래서 여기에 내 코드가 app / models / user.rb에있다 .

class User
  has_many :ownerships, foreign_key: "offerer_id",
                         dependent: :destroy
  has_many :owned_products, through: :ownerships,
                             source: :product
  has_many :future_ownerships, -> { where owning_date: nil, giving_date: nil },
                               class_name: "Ownership",
                               foreign_key: "offerer_id"
  has_many :wanted_products, through: :future_ownerships,
                             source: :product
end

그래서 has_many :future_ownershipshas_many :wanted_products 삭제하고 app / models / ownership.rb에 범위를 만들었습니다.

class Ownership
  scope :future, -> { where owning_date: nil, giving_date: nil }
end

이제 나는 미래 소유권을 찾을 수 있습니다 : user.ownerships.future . 하지만 내가 모르는 것은 원하는 제품을 검색하는 방법입니다. 내 app / models / product.rb 의 범위를 다음과 같이 입력 할 수있는 방법은 무엇입니까?

user.owned_products.wanted

https://ffff65535.com


특히 제품의 하위 집합을 열심히로드해야하는 경우에는 본질적으로 연결 상태가 좋지 않습니다.

그러나 필요한 범위를 얻으려면 Product 모델에 필터를 추가하고 정의 된 모델과 다른 모델에 필터가 적용되므로 일반 SQL에 의존해야합니다.

class Product
  # not tested 
  scope :wanted, ->{ where("ownerships.owning_dates IS NULL AND ...") }
end

IMHO 첫 번째 솔루션으로 더 나아졌습니다. 그 이유는 어떤 이유로 여러 사용자 중 한 블록 안에 해당 범위를 적용하면 제품로드가 뜨거울지라도 O (n) 벽에 부딪 힐 수 있기 때문입니다.

User.includes(:owned_products).each do |user|
  user.onwned_products.wanted # => SQL connection
end

업데이트 : ActiveRecord 의 놀랍도록 문서화되지 않은 기능을 merge 하는 방법에 대해 알아 냈습니다.

다른 용도로는 조인을 수행하고 조인 된 모델에서 명명 된 범위로 필터링 할 수 있습니다

다시 말해서 다음을 할 수 있습니다.

user.owned_products.merge(Ownership.future)

강력한 종료하십시오!





model-associations