【问题标题】:How do I do where queries across virtual attributes?如何跨虚拟属性进行 where 查询?
【发布时间】:2015-03-12 09:36:34
【问题描述】:

我有一个Node 模型,它有一个虚拟属性user_tags

这是控制台上的样子:

[42] pry(main)> n = Node.first
  Node Load (0.5ms)  SELECT  "nodes".* FROM "nodes"   ORDER BY "nodes"."id" ASC LIMIT 1
=> #<Node id: 6, name: "10PP Form Video", family_tree_id: 57, user_id: 57, media_id: 118, media_type: "Video", created_at: "2015-03-09 20:57:19", updated_at: "2015-03-09 20:57:19", circa: nil, is_comment: nil>
[43] pry(main)> n.user_tags
  ActsAsTaggableOn::Tag Load (0.3ms)  SELECT "tags".* FROM "tags" INNER JOIN "taggings" ON "tags"."id" = "taggings"."tag_id" WHERE "taggings"."taggable_id" = $1 AND "taggings"."taggable_type" = $2 AND "taggings"."context" = 'user_tags'  [["taggable_id", 6], ["taggable_type", "Node"]]
=> [#<ActsAsTaggableOn::Tag id: 6, name: "danny@test.com", taggings_count: 1>, #<ActsAsTaggableOn::Tag id: 4, name: "gerry@test.com", taggings_count: 1>]

我想做的是在我的Node 模型上创建一个scope,以仅映射到具有user_tags 的那些节点。即!user_tags.empty?.

我该怎么做?

【问题讨论】:

  • 你可以试试scope :no_tags, lambda { where('user_tags = ?', nil) }scope :no_tags, lambda { where("user_tags IS NULL") }
  • @Sontya 我尝试了第一个,得到了这个错误:&gt; Node.where('user_tags = ?', nil) Node Load (0.9ms) SELECT "nodes".* FROM "nodes" WHERE (user_tags = NULL) PG::UndefinedColumn: ERROR: column "user_tags" does not exist LINE 1: SELECT "nodes".* FROM "nodes" WHERE (user_tags = NULL)。我也尝试了第二个并遇到了同样的问题。我收到这个错误是因为我是在命令行上尝试的,而不是把它放在作用域上的 lambda 中吗?
  • @Sontya 不,lambda 不是问题。我只是用模型上的实际范围试了一下,我得到了同样的错误。

标签: ruby-on-rails ruby-on-rails-4 activerecord virtual-attribute


【解决方案1】:
scope :with_tags, ->() { joins(:tags).uniq }

您不能使用where,因为标签存储在与您的模型不同的表中 - 您必须先与另一个表进行连接。现在可爱的部分 - joins 执行 INNER JOIN 这意味着它不会加载在另一个表中没有匹配记录的模型。现在剩下的就是删除重复项(如果您有带有 n 个标签的模型,JOIN 将返回该记录 n 次)

【讨论】:

  • 啊……天才。这行得通。谁会想到joins 也适用于虚拟属性。那是柯尔!非常感谢孟!
  • tags 不是虚拟属性 - 它是一个关联。
  • 所以acts_as_taggable 将其添加为关联?我没有添加任何显式关联,gem 似乎表明它添加了虚拟属性,但我可能是错的。
  • 是的,它添加了这个关联,然后添加了一个虚拟属性tag_list。顺便说一句,对tag_list 非常小心,它在内部使用pluck,所以经常会导致N+1 问题。
  • tags 是一个常规关联,可以使用includes 预加载以避免N+1,所以没有问题。
猜你喜欢
  • 2012-03-29
  • 1970-01-01
  • 2012-12-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多