Programing

Rails 3에서 ActiveRecord 연결 범위를 어떻게 지정합니까?

crosscheck 2020. 12. 9. 07:50
반응형

Rails 3에서 ActiveRecord 연결 범위를 어떻게 지정합니까?


Rails 3 프로젝트가 있습니다. Rails 3에서는 Arel과 한 스코프를 재사용하여 다른 스코프를 구축 할 수있는 기능이 제공되었습니다. 관계를 정의 할 때 범위를 사용하는 방법이 있는지 궁금합니다 (예 : "has_many").

권한 열이있는 레코드가 있습니다. 내 권한 열을 고려하여 레코드 (관계를 통해 액세스 한 레코드 포함)를 필터링하는 default_scope를 만들고 싶습니다.

현재 Rails 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의 범위를 상위 계층 (컨트롤러 또는 모델에 직접 액세스하는 다른 모든 것)에 노출하지 않도록 권장하며 이렇게하려면 다음이 필요합니다.

  1. 범위를 만들고 모델의 메서드를 통해 노출합니다. 이 방법은 컨트롤러에 노출하는 방법입니다.
  2. 모델을 컨트롤러에 노출하지 않는다면 (따라서 그 위에 일종의 서비스 레이어가 있음) 괜찮습니다. 부패 방지 계층 서비스이며 범위 구현 방법에 대해 너무 걱정하지 않고 모델의 범위에 액세스 할 수 있습니다.

연결 확장은 어떻습니까?

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.reflection은 연관을 설명하는 반사 객체를 반환합니다. proxy_association.target은 belongs_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 

여러 모델의 범위를 병합하기 위해 병합 방법을 사용할 수 있습니다 . 자세한 내용은이 railscast 에서 병합을 검색하십시오.


사용자의 주문 만 받으려는 경우 관계를 사용하지 않는 이유는 무엇입니까?

컨트롤러의 current_user 메서드에서 현재 사용자에 액세스 할 수 있다고 가정합니다.

@my_orders = current_user.orders

이렇게하면 사용자의 특정 주문 만 표시됩니다. 다음을 사용하여 더 깊은 리소스를 얻기 위해 임의로 중첩 된 조인을 수행 할 수도 있습니다.joins

current_user.orders.joins(:level1 => { :level2 => :level3 }).where('level3s.id' => X)

참고 URL : https://stackoverflow.com/questions/2412340/how-do-you-scope-activerecord-associations-in-rails-3

반응형