Ruby-on-Rails: Multiple has_many :through possible?

后端 未结 4 1798
感情败类
感情败类 2020-11-29 23:23

Is it possible to have multiple has_many :through relationships that pass through each other in Rails? I received the suggestion to do so as a solution for ano

相关标签:
4条回答
  • 2020-11-30 00:13

    Edit:

    Rails 3.1 supports nested associations. E.g:

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

    There is no need for the solution given below. Refer to this screencast for more details.

    Original Answer

    You are passing a has_many :through association as a source for another has_many :through association. I don't think it will work.

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

    You have three approaches to solving this issue.

    1) Write an association extension

     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
    

    Now you can get the friends comments as follows:

    user.friends.comments
    

    2) Add a method to the User class.

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

    Now you can get the friends comments as follows:

    user.friends_comments
    

    3) If you want this to be even more efficient then:

      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
    

    Now you can get the friends comments as follows:

    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)
    
    0 讨论(0)
  • 2020-11-30 00:16

    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
    
    0 讨论(0)
  • 2020-11-30 00:22

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

    0 讨论(0)
  • 2020-11-30 00:26

    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/

    0 讨论(0)
提交回复
热议问题