복붙노트

[RUBY-ON-RAILS] 루비 온 레일 : 여러 has_many : 수를 통해?

RUBY-ON-RAILS

루비 온 레일 : 여러 has_many : 수를 통해?

레일에서 서로를 통과 관계를 통해 : 그것은 여러 has_many을 할 수 있습니까? 내가 게시 된 또 다른 질문에 대한 해결책으로 그렇게 할 수있는 제안을 받았지만, 일에 그것을 얻을 수 없었습니다.

A는 테이블 조인을 통해 친구 순환 협회입니다. 내가 단일 쿼리에 그의 친구에 의해 모든 코멘트를 얻을 수 user.friends_comments 같은 것을 사용자를 가지고 할 수 있습니다 통해 friends_comments을 위해 : 목표는 has_many을 만드는 것입니다.

class User
  has_many :friendships
  has_many :friends, 
           :through => :friendships,
           :conditions => "status = #{Friendship::FULL}"
  has_many :comments
  has_many :friends_comments, :through => :friends, :source => :comments
end

class Friendship < ActiveRecord::Base
  belongs_to :user
  belongs_to :friend, :class_name => "User", :foreign_key => "friend_id"
end

이 멋지다, 그리고 의미가 있지만 나를 위해 작동하지 않습니다. 이것은 내가 사용자의 friends_comments에 액세스하려고 할 때 관련 부분에지고있어 오류입니다 : ERROR : 열 users.user_id가 존재하지 않습니다 :. "코멘트"를 선택 * INNER이 "코멘트"ON "사용자"가입 "코멘트".user_id = "사용자"의은 .ID WHERE (( "사용자".user_id = 1) AND ((상태 = 2)))

난 그냥 user.friends, 일을 입력하면,이 그것을 실행하는 쿼리는 다음과 같습니다 :. "사용자"를 선택 INNER * "는 사용자가"ON "우정"가입 "사용자".ID = "우정"보낸이 .friend_id WHERE (( "우정".user_id = 1) AND ((상태 = 2)))

그래서 부적절하게 테이블을 조인으로 사용자 클래스를 사용하려고하는 다음 완전히 우정 관계를 통해 원래의 has_many 잊고있는 것처럼 보인다합니다.

내가 뭔가 잘못하고, 또는이 단순히 수없는 건가요?

해결법

  1. ==============================

    1.편집하다:

    편집하다:

    협회 중첩 3.1 지원 레일. 예컨대 :

    has_many :tasks
    has_many :assigments, :through => :tasks
    has_many :users, :through => :assignments
    

    아래의 솔루션에 대한 필요가 없습니다. 자세한 내용은이 스크린 캐스트를 참조하십시오.

    원래 대답

    당신은 has_many 전달됩니다 협회를 통해 다른 has_many의 소스로 :를 통해 협회. 나는 그것이 작동합니다 생각하지 않습니다.

      has_many :friends, 
               :through => :friendships,
               :conditions => "status = #{Friendship::FULL}"
      has_many :friends_comments, :through => :friends, :source => :comments
    

    이 문제를 해결하는 세 가지 방법이있다.

    1) 연관 연장 쓰기

     has_many  :friends, 
               :through => :friendships,
               :conditions => "status = #{Friendship::FULL}" do
         def comments(reload=false)
           @comments = nil if reload 
           @comments ||=Comment.find_all_by_user_id(map(&:id))
         end
     end
    

    다음과 같이 이제 친구에게 의견을 얻을 수 있습니다 :

    user.friends.comments
    

    2) 사용자 클래스에 메서드를 추가합니다.

      def friends_comments(reload=false)
        @friends_comments = nil if reload 
        @friends_comments ||=Comment.find_all_by_user_id(self.friend_ids)
      end
    

    다음과 같이 이제 친구에게 의견을 얻을 수 있습니다 :

    user.friends_comments
    

    3) 당신은이 후 더욱 효율적으로 할 경우 :

      def friends_comments(reload=false)
        @friends_comments = nil if reload 
        @friends_comments ||=Comment.all( 
                 :joins => "JOIN (SELECT friend_id AS user_id 
                                  FROM   friendships 
                                  WHERE  user_id = #{self.id}
                            ) AS friends ON comments.user_id = friends.user_id")
      end
    

    다음과 같이 이제 친구에게 의견을 얻을 수 있습니다 :

    user.friends_comments
    

    모든 방법은 결과를 캐시합니다. 당신이 다시로드 할 경우 결과는 다음을 수행 :

    user.friends_comments(true)
    user.friends.comments(true)
    

    또는 더 나은 아직 :

    user.friends_comments(:reload)
    user.friends.comments(:reload)
    
  2. ==============================

    2.문제를 해결하는 플러그인이 있습니다,이 블로그에서보세요.

    문제를 해결하는 플러그인이 있습니다,이 블로그에서보세요.

    당신은 플러그인을 설치

    script/plugin install git://github.com/ianwhite/nested_has_many_through.git
    
  3. ==============================

    3.이 과거에 작동하지 않았지만, 지금은 레일 3.1에서 잘 작동합니다.

    이 과거에 작동하지 않았지만, 지금은 레일 3.1에서 잘 작동합니다.

  4. ==============================

    4.나는이 블로그 항목이 유용하다는 것을 발견 http://geoff.evason.name/2010/04/23/nested-has_many-through-in-rails-or-how-to-do-a-3-table-join /

    나는이 블로그 항목이 유용하다는 것을 발견 http://geoff.evason.name/2010/04/23/nested-has_many-through-in-rails-or-how-to-do-a-3-table-join /

  5. from https://stackoverflow.com/questions/2383479/ruby-on-rails-multiple-has-many-through-possible by cc-by-sa and MIT license