programing

Ruby-on-Rails : 다중 has_many : through 가능?

copyandpastes 2021. 1. 14. 23:35
반응형

Ruby-on-Rails : 다중 has_many : through 가능?


has_many :throughRails에서 서로를 통과하는 여러 관계 를 가질 수 있습니까? 게시 한 다른 질문에 대한 해결책으로 그렇게하라는 제안을 받았지만 제대로 작동하지 못했습니다.

친구는 조인 테이블을 통한 순환 연결 입니다. 목표는 has_many :throughfor 를 만드는 friends_comments것이므로 a 가져 와서 친구의 모든 댓글을 단일 쿼리로 가져 오는 User것과 같은 작업을 수행 할 수 있습니다 user.friends_comments.

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: column users.user_id does not exist
: SELECT "comments".* FROM "comments" INNER JOIN "users" ON "comments".user_id = "users".id WHERE (("users".user_id = 1) AND ((status = 2)))

작동하는 user.friends를 입력하면 다음과 같은 쿼리가 실행됩니다.
: SELECT "users".* FROM "users" INNER JOIN "friendships" ON "users".id = "friendships".friend_id WHERE (("friendships".user_id = 1) AND ((status = 2)))

그래서 has_many우정 관계를 통해 원본 완전히 잊은 것 같고 , 부적절하게 User 클래스를 조인 테이블로 사용하려는 것 같습니다.

내가 뭔가를 잘못하고 있습니까, 아니면 이것이 단순히 불가능합니까?


편집하다:

Rails 3.1은 중첩 된 연결을 지원합니다. 예 :

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

아래에 주어진 솔루션이 필요하지 않습니다. 자세한 내용은 스크린 캐스트를 참조하십시오.

원래 답변

has_many :through다른 has_many :through연결 의 소스로 연결을 전달하고 있습니다. 나는 그것이 작동 할 것이라고 생각하지 않는다.

  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) User클래스에 메서드를 추가합니다 .

  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

All methods cache the results. If you want to reload the results do the following:

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

OR better still:

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

There is a plugin that solves your problem, take a look at this blog.

You install the plugin with

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

Although this didn't work in the past, it works fine in Rails 3.1 now.


I found this blog entry to be useful: http://geoff.evason.name/2010/04/23/nested-has_many-through-in-rails-or-how-to-do-a-3-table-join/

ReferenceURL : https://stackoverflow.com/questions/2383479/ruby-on-rails-multiple-has-many-through-possible

반응형