【问题标题】:Customizing the query on a Rails ActiveRecord has_many association在 Rails ActiveRecord has_many 关联上自定义查询
【发布时间】:2013-12-07 21:28:48
【问题描述】:

我正在使用 acts-as-taggable-on gem 并希望在 ActsAsTaggableOn::Tag 上实现一个名为 #related_tags 的关联。

此方法的要点是,我想返回与我选择的任何特定标签一起标记的所有标签。例如,给定以下内容:

Tags
id  name
1   happy
2   bright
3   warm

Posts
id  tags
1   happy,bright
2   bright,warm

那么 ActsAsTaggableOn::Tag.find(1).related_tags 应该包含 Bright (2) 的 Tag 实例,但是 ActsAsTaggableOn::Tag.find(2).related_tags 应该包含happy 和 warm (1 和3).

我让 sql 在 sql shell 中工作,即:

SELECT * FROM tags WHERE id IN (SELECT tags.id FROM taggings JOIN tags ON tags.id = taggings.tag_id WHERE taggings.taggable_id IN (SELECT taggable_id FROM taggings WHERE taggings.tag_id = #{tag.id}) AND tags.id <> #{tag.id});

并尝试将其添加到关联中:

ActsAsTaggableOn::Tag.class_eval do
   has_many :related_tags, ->(tag) { where( <above sql>, :tag => tag.id) },:class_name => "ActsAsTaggableOn::Tag", :foreign_key => 'id'
end

这似乎对我有用...但它生成的 SQL 是:

SELECT "tags".* FROM "tags" WHERE "tags"."id" = $1 AND (tags.id IN (SELECT tags.id FROM taggings JOIN tags ON tags.id = taggings.tag_id WHERE taggings.taggable_id IN (SELECT taggings.taggable_id FROM taggings WHERE taggings.tag_id = 10) AND tags.id <> 10))  [["id", 10]]

所以这里的问题是额外的 "tags"."id" = $1 其中 $1 是当前标签 id...但我不知道它是如何添加的或如何删除它。如果我采用生成的 sql 并删除该条件,它就可以正常工作。有其他人知道为什么要添加它以及如何摆脱它吗?

Relevant docs are here,但没有多大帮助。

提前致谢!

【问题讨论】:

  • 顺便说一句,我知道我可以创建一个实例方法来实现上面的 sql,但是我正在渲染标签集合,所以最好能够使用 ::includes 来预取他们都在同一时间。

标签: sql ruby-on-rails activerecord associations acts-as-taggable-on


【解决方案1】:

我在 has_many through 关系上执行 .where 时遇到问题 - 例如:Update.first.tags.where(...)。我发现它只是查询已经与该更新关联的标签。所以调用首先是查询当前与 Update.first 关联的标签,然后是我的 SQL 查询。

您的情况可能会发生类似的情况。

另外,您还有另一个兴趣点,标签:tag.id。这是我能想到的唯一两个可以添加“标签”的地方。“id” = $1

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多