我有以下型号:
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;
我尝试过添加
has_many :tags, :through => :gallery_tags, :foreign_key => :gallery_id
到Image,导致Image.find(34).tags导致
SELECT `tags`.* FROM `tags` INNER JOIN `gallery_tags` ON `tags`.id = `gallery_tags`.tag_id WHERE ((`gallery_tags`.gallery_id = 34))
(它没有在查询中使用图片的gallery_id),然后我尝试添加
has_many :bookmarked_tags, :through => :bookmarked_images, :source => :tags
到User,导致User.find(1).bookmarked_tags导致
ActiveRecord :: HasManyThroughSourceAssociationMacroError:无效 源反射宏:has_many:通过for_many :bookmarked_tags,:through =&gt; :bookmarked_images。使用:来源 指定源反射。
那么:我怎样才能让Rails运行我用User.find(1).bookmarked_tags发布的查询?
答案 0 :(得分:3)
有两种解决方案
第一个解决方案:
在数据库中创建一个类似于连接表的视图:
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查找所需):
<强> tag.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
添加bookmarked_tags
方法
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