如果我有3个模型之间的多态关联:
评论
belongs_to :book, :class_name => 'Book', :foreign_key => 'ref_id', conditions: "comments.ref_type = 'Book'"
belongs_to :article, :class_name => 'Article', :foreign_key => 'ref_id', conditions: "comments.ref_type = 'Article'"
belongs_to :ref, :polymorphic => true
对于给定的注解列表,如何从Book
和Article
模型的Title
列中选择不同的值?
例如,如果我必须列出在某个时间段内有评论的书籍和文章的标题,那么我该怎么做呢?我可以很容易地选择评论列表,但我如何从Book
和Article
中选择相关的唯一标题呢?
例如:
Book
+--------------+
| Id | Title |
+----+---------+
| 1 | 'Book1' |
| 2 | 'Book2' |
| 3 | 'Book3' |
+--------------+
Article
+-----------------+
| Id | Title |
+----+------------+
| 1 | 'Article1' |
| 2 | 'Article2' |
+-----------------+
Comments
+--------------------------------------+
| Id | comment | ref_id | ref_type |
+----+------------+--------+-----------+
| 1 | 'comment1' | 1 | Book |
| 2 | 'comment2' | 1 | Book |
| 3 | 'comment3' | 1 | Article |
| 4 | 'comment4' | 3 | Book |
+--------------------------------------+
我需要的标题列表是'Book1'
,'Book3'
,'Article1'
。
4条答案
按热度按时间ddrv8njm1#
简单方法:
获取所有注解,eager加载它们的引用,并返回一个包含唯一标题的数组。eager加载部分不是严格必要的,但它可能会执行得更好。执行3个查询,一个针对注解,一个针对每种引用。您可以将 all 替换为任何范围。请注意,这将获取所有注解及其引用,并使用ruby将其转换为数组,而不是SQL。这非常有效。但是性能可能会受到影响。通常最好使用 distinct 来获得唯一值,然后使用 pluck 来获得这些值的数组。
这种方法适用于所有类型的ref。因此,如果我们引入第三种ref,例如 Post,它将自动包含在此查询中。
复用方式:
此作用域使用arel和子查询的UNION来获取标题。它基本上将引用的标题添加到注解对象。由于作用域应该是可链接的,因此它返回ActiveRecord Relation而不是数组。要获取不同的标题,请追加 distinct.pluck(:title)。
此作用域生成的SQL查询如下所示:
使用rails 5.1.2和sqlite进行测试。
vxf3dgd42#
我认为最简单的方法是在
Book
和Article
上定义.titles_for_comments
作用域,当给定comments
的集合时,可以从每个表中选择不同的标题,而不直接使用Arel
API或迭代数组。然后为Comment
定义一个.distinct_titles
作用域,该作用域使用[Book|Article].titles_for_comments
。例如,下面的模型和作用域定义允许您通过调用Comment.distinct_titles
为任何给定的Comment::ActiveRecord_Relation
示例查找不同的Book和Article标题您可以下载此Gist并使用
ruby polymorphic_query_test.rb
运行它,测试应该通过https://gist.github.com/msimonborg/907eb513fdde9ab48ee881d43ddb8378cnwbcb6i3#
试试这个
0vvn1miw4#
我建议你看看这个教程:https://web.archive.org/web/20180928102044/http://karimbutt.github.io:80/blog/2015/01/03/step-by-step-guide-to-polymorphic-associations-in-rails/,看看它是否适合你。
如果您控制模型代码,我会将注解设置为
belong_to
一个通用的可注解对象。示例:然后呢
然后给出任何一组注解
目前,仅仅获取标题似乎需要做很多工作,但如果你坚持这个项目,我希望书籍和文章能够分享 * 很多 * 这种类型的代码,以及将来可能添加其他可注解的对象。总体而言,拥有一个通用对象将保存大量工作。