Rails 3의 ActiveRecord 연관성을 어떻게 범위를 유지합니까?
-
18-09-2019 - |
문제
Rails 3 프로젝트가 있습니다. Rails 3과 함께 Arel과 다른 범위를 재사용하여 다른 범위를 구축 할 수있는 능력이 있습니다. 관계를 정의 할 때 스코프를 사용하는 방법이 있는지 궁금합니다 (예 : "has_many").
권한 열이있는 레코드가 있습니다. 권한 열을 고려하여 기본값을 구축하여 (관계를 통해 액세스 한 레코드조차도) 필터링됩니다.
현재 레일 3에서 Default_scope (내가 찾은 패치 포함)는 Proc (후기 가변 바인딩에 필요한)를 통과시키는 실행 가능한 수단을 제공하지 않습니다. 명명 된 스코프를 전달할 수있는 has_many를 정의 할 수 있습니까?
지명 된 범위를 재사용한다는 아이디어는 다음과 같습니다.
Orders.scope :my_orders, lambda{where(:user_id => User.current_user.id)}
has_many :orders, :scope => Orders.my_orders
또는 관계에서 이름이 지정된 스코프를 암시 적으로 코딩하는 것과 같습니다.
has_many :orders, :scope => lambda{where(:user_id => User.current_user.id)}
나는 단순히 늦은 바인딩으로 default_scope를 적용하려고 노력하고 있습니다. Arel 접근 방식을 사용하는 것이 좋습니다 (있는 경우). 그러나 실행 가능한 옵션을 사용합니다.
현재 사용자를 언급하고 있기 때문에 마지막으로 평가되지 않은 조건에 따라 다음과 같이 의존 할 수 없습니다.
has_many :orders, :conditions => ["user_id = ?", User.current_user.id]
해결책
나는 당신이 살펴 보는 것이 좋습니다 "이름이 지정된 범위가 죽었다"
저자는 Arel이 얼마나 강력한 지 설명합니다 :)
도움이되기를 바랍니다.
2014 년 3 월 1 일 편집
일부 의견에 따르면, 차이는 이제 개인적인 취향의 문제입니다.
그러나 나는 여전히 개인적으로 Arel의 범위를 상단 계층 (컨트롤러 또는 모델에 직접 액세스하는 다른 것)에 노출하지 않는 것이 좋습니다.
- 스코프를 만들고 모델에서 메소드를 통해 노출하십시오. 이 방법은 컨트롤러에 노출되는 방법입니다.
- 모델을 컨트롤러에 노출시키지 않으면 (따라서 그 위에 어떤 종류의 서비스 계층이 있습니다) 괜찮습니다. 반부패 층 ~이다 서비스와 스코어가 구현되는 방법에 대해 너무 걱정하지 않고 모델의 범위에 액세스 할 수 있습니다.
다른 팁
연관 확장은 어떻습니까?
class Item < ActiveRecord::Base
has_many :orders do
def for_user(user_id)
where(user_id: user_id)
end
end
end
Item.first.orders.for_user(current_user)
업데이트 : 클래스 방법이나 범위와 달리 협회 확장에 대한 이점을 지적하고 싶습니다. 협회 대리의 내부에 액세스 할 수 있다는 것입니다.
proxy_association.owner는 협회가 일부인 객체를 반환합니다. proxy_association. 반사는 연관성을 설명하는 반사 객체를 반환합니다. proxy_association.target은 solgs_to 또는 has_one의 관련 객체를 반환하거나 has_many 또는 has_and_belongs_to_many의 관련 객체 모음을 반환합니다.
자세한 내용은 여기를 참조하십시오. http://guides.rubyonrails.org/association_basics.html#association-extensions
스코프 대신 방금 클래스 메토드를 정의하고 있습니다.
def self.age0 do
where("blah")
end
나는 다음과 같은 것을 사용합니다.
class Invoice < ActiveRecord::Base
scope :aged_0, lambda{ where("created_at IS NULL OR created_at < ?", Date.today + 30.days).joins(:owner) }
end
당신이 사용할 수있는 병합 다른 모델에서 스코프를 병합하기위한 방법. 자세한 내용은 Merge를 검색하십시오 Railscast
사용자의 주문을 받으려고한다면 관계를 사용하지 않는 이유는 무엇입니까?
현재 사용자가 컨트롤러의 current_user 메소드에서 액세스 할 수 있다고 가정합니다.
@my_orders = current_user.orders
이를 통해 사용자의 특정 주문 만 표시됩니다. 또한 임의로 중첩 된 조인을 수행하여 사용하여 더 깊은 리소스를 얻을 수 있습니다. joins
current_user.orders.joins(:level1 => { :level2 => :level3 }).where('level3s.id' => X)