2011-10-30 11 views
0

私は、次のモデルがあります:Railsの複数のINNER JOINはhas_many関係ですか?

class Image < ActiveRecord::Base 
    belongs_to :gallery 
    has_many :bookmarks 
    has_many :gallery_tags, :foreign_key => :gallery_id 
end 

class Bookmark < ActiveRecord::Base 
    belongs_to :user 
    belongs_to :image 
    has_many :gallery_tags, :through => :image, :source => :gallery_tags 
end 


class GalleryTag < ActiveRecord::Base 
    belongs_to :gallery 
    belongs_to :tag 
end 

class Gallery < ActiveRecord::Base 
    belongs_to :provider 
    has_many :images 
    belongs_to :user 
    has_many :gallery_tags 
    has_many :tags, :through => :gallery_tags 
end 

class Tag < ActiveRecord::Base 
end 

class User < ActiveRecord::Base 
    has_many :bookmarks 
    has_many :galleries 
end 
私は

User.find(1).bookmarked_tags 

を行うと、画像に関連するギャラリーを介してユーザのブックマークすべての画像に関連付けられたすべてのタグを検索できるようにしたいと思い

。タグはギャラリーに関連付けられています。

クエリは、このように見て終わるでしょう:

SELECT 
    tags.* 
FROM 
    tags 
    INNER JOIN gallery_tags ON gallery_tags.tag_id = tags.id 
    INNER JOIN images ON gallery_tags.gallery_id = images.gallery_id 
    INNER JOIN bookmarks ON images.id = bookmarks.image_id 
WHERE 
    bookmarks.user_id = 1 
GROUP BY 
    tags.id; 

私はImage.find(34)を引き起こす画像に

has_many :tags, :through => :gallery_tags, :foreign_key => :gallery_id 

を追加しようとしました

をもたらすことが.tags
SELECT `tags`.* FROM `tags` INNER JOIN `gallery_tags` ON `tags`.id = `gallery_tags`.tag_id WHERE ((`gallery_tags`.gallery_id = 34)) 

(これは画像のgallery_idをクエリに使用していません)、次に私は

を追加しようとしましたUser.findは、(1)だから、

ActiveRecord::HasManyThroughSourceAssociationMacroError: Invalid source reflection macro :has_many :through for has_many :bookmarked_tags, :through => :bookmarked_images. Use :source to specify the source reflection.

をもたらすことが.bookmarked_tagsなり、ユーザーへ

has_many :bookmarked_tags, :through => :bookmarked_images, :source => :tags 

:どのように私はUser.find(1)で掲示クエリを実行するためのRailsを得ることができます。 bookmarked_tags?

答えて

3

2つのソリューション

最初のソリューションあります

CREATE VIEW user_bookmarks_tags (
    SELECT 
    bookmarks.user_id AS user_id 
    gallery_tags.tag_id AS tag_id 
    FROM 
    gallery_tags 
    INNER JOIN images ON gallery_tags.gallery_id = images.gallery_id 
    INNER JOIN bookmarks ON images.id = bookmarks.image_id 
    GROUP BY 
    user_id, tag_id 
) 

(あなたは、移行の内側にこれを行うことができます):

が結合テーブルのように動作し、データベース内のビューを作成します。 このビューは、列を含む「表」のように機能します。user_id | tag_id

今、私たちはhas_and_belongs_to_manyを使用して、当社のモデルを適応させることができます。

user.rb

class User < ActiveRecord::Base 
    has_many :bookmarks 
    has_many :galleries 

    # we use our magic (view) join table here! 
    has_and_belongs_to_many :tags, :join_table => :user_bookmarks_tags 
end 

tag.rb

class Tag < ActiveRecord::Base 
    # we use our magic (view) join table here 
    has_and_belongs_to_many :users, :join_table => :user_bookmarks_tags 
end 

今、あなたが行うことができます:User.find(1).tagsまたはTag.find(1).users :)


第二の溶液

ビューずに手動で参加してください:

タグ:

が不足している関係を(自動化するために必要なFOREIGN_KEYのルックアップに参加します)を定義します。RB

class Tag < ActiveRecord::Base 
    has_many :gallery_tags 
end 

gallery_tag.rb

class GalleryTag < ActiveRecord::Base 
    belongs_to :gallery 
    belongs_to :tag 
    # new: 
    has_many :images, :through => :gallery 
end 

今、私たちは私たちのuser.rb

class User < ActiveRecordBase 
    has_many :bookmarks 
    has_many :galleries 

    def bookmarked_tags 
    Tag.joins(:gallery_tags => {:images => :bookmarks}).where('bookmarks.user_id = ?', self.id).group('tags.id') 
    end 
end 
+0

うわー、面白いにbookmarked_tagsメソッドを追加することができます。私は方法が必要だと思ったが、私はArelの.joinsを使ったことはなかった。ありがとう、これは動作します(私は2番目の解決策に行きました)。 –