如果涉及多态关联,如何创建'has_many through'关联?
How to create a 'has_many through' association if a polymorphic association is involved?
我有 4 个模型:模型 1 与模型 2 相关联,模型 2 与模型 3 相关联。模型 2 和模型 3 通过多态关联与模型 4 相关联。这一切都有效。我在指定模型 1 和模型 4 之间的关联时遇到问题,因此它们以两种方式相关:
- 模型 1 - 模型 2 - 模型 4
- 模型 1 - 模型 2 - 模型 3 - 模型 4
下面是所有关联,除了模型 1 和模型 4 之间的关联:
作者模型:
has_many :books, dependent: :destroy
图书型号:
belongs_to :author
has_many :chapters, dependent: :destroy
has_many :titles, as: :titlesource, # Polymorphic Association
dependent: :destroy
章节模型:
belongs_to :book
has_many :titles, as: :titlesource, # Polymorphic Association
dependent: :destroy
标题模型:
belongs_to :titlesource, polymorphic: true
问题:假设你有上面的联想,你想知道一个author
有一个titles
,不管它们是不是一个book-title 或 chapter-title。我应该使用哪些关联来扩展上述设置? (我假设有 has_many through
)
更新: 如果我要找的只是 book-titles,我希望将 has_many :titles, through: :books
添加到 Author
模型中上班。但事实并非如此。如果我添加该关联,则 Author.first.titles
会产生错误 undefined method 'titles'
。我认为这与多态关联和命名有关......?我做错了什么?
章节标题就更难了。该关联通过 Book
模型,然后通过 Chapter
模型,然后到达 Title
模型。如何将这些标题包含在作者模型中?我认为它必须是具有以下逻辑的代码(但显然这段代码是不正确的):
has_many :titles, through: :books && :books:chapters
更新:给出的两个答案使用SQL。这些解决方案不会向数据库发送大量查询,如果经常使用该方法会导致问题吗?这些方法中的一种在性能上是否优于另一种?
如果您要在 Author
上使用像 has_many :titles, through: :books
这样的关联,只要您在 titlesource_id
和 titlesource_type
Title
模型迁移。
但是,如果您像这样添加另一个来获取章节中的标题 has_many :titles, through: :chapters
,它会覆盖第一个,并且它只会获取 titlesource_type = 'Chapter'
的标题。
因此,如果您不介意,我建议您的解决方案 sql 是在 Author 模型中实现这样的方法。
def titles
Title.where(
"(titles.titlesource_type = 'Book'
AND titles.titlesource_id
IN (SELECT books.id FROM books WHERE books.author_id = #{id}))
OR (titles.titlesource_type = 'Chapter'
AND titles.titlesource_id
IN (SELECT chapters.id
FROM books
INNER JOIN chapters ON chapters.book_id = books.id
WHERE books.author_id = #{id}))"
)
end
如果您不需要 ActiveRecord 方法(如 where
或 order
),那么这将为您提供一个标题数组。
def titles_array # sacrificing ActiveRecord methods
books.collect { |b| b.titles + b.chapters.collect { |c| c.titles } }
end
您仍然可以对 titles_array.first.author
等单个数组元素使用 AR 方法
我有 4 个模型:模型 1 与模型 2 相关联,模型 2 与模型 3 相关联。模型 2 和模型 3 通过多态关联与模型 4 相关联。这一切都有效。我在指定模型 1 和模型 4 之间的关联时遇到问题,因此它们以两种方式相关:
- 模型 1 - 模型 2 - 模型 4
- 模型 1 - 模型 2 - 模型 3 - 模型 4
下面是所有关联,除了模型 1 和模型 4 之间的关联:
作者模型:
has_many :books, dependent: :destroy
图书型号:
belongs_to :author
has_many :chapters, dependent: :destroy
has_many :titles, as: :titlesource, # Polymorphic Association
dependent: :destroy
章节模型:
belongs_to :book
has_many :titles, as: :titlesource, # Polymorphic Association
dependent: :destroy
标题模型:
belongs_to :titlesource, polymorphic: true
问题:假设你有上面的联想,你想知道一个author
有一个titles
,不管它们是不是一个book-title 或 chapter-title。我应该使用哪些关联来扩展上述设置? (我假设有 has_many through
)
更新: 如果我要找的只是 book-titles,我希望将 has_many :titles, through: :books
添加到 Author
模型中上班。但事实并非如此。如果我添加该关联,则 Author.first.titles
会产生错误 undefined method 'titles'
。我认为这与多态关联和命名有关......?我做错了什么?
章节标题就更难了。该关联通过 Book
模型,然后通过 Chapter
模型,然后到达 Title
模型。如何将这些标题包含在作者模型中?我认为它必须是具有以下逻辑的代码(但显然这段代码是不正确的):
has_many :titles, through: :books && :books:chapters
更新:给出的两个答案使用SQL。这些解决方案不会向数据库发送大量查询,如果经常使用该方法会导致问题吗?这些方法中的一种在性能上是否优于另一种?
如果您要在 Author
上使用像 has_many :titles, through: :books
这样的关联,只要您在 titlesource_id
和 titlesource_type
Title
模型迁移。
但是,如果您像这样添加另一个来获取章节中的标题 has_many :titles, through: :chapters
,它会覆盖第一个,并且它只会获取 titlesource_type = 'Chapter'
的标题。
因此,如果您不介意,我建议您的解决方案 sql 是在 Author 模型中实现这样的方法。
def titles
Title.where(
"(titles.titlesource_type = 'Book'
AND titles.titlesource_id
IN (SELECT books.id FROM books WHERE books.author_id = #{id}))
OR (titles.titlesource_type = 'Chapter'
AND titles.titlesource_id
IN (SELECT chapters.id
FROM books
INNER JOIN chapters ON chapters.book_id = books.id
WHERE books.author_id = #{id}))"
)
end
如果您不需要 ActiveRecord 方法(如 where
或 order
),那么这将为您提供一个标题数组。
def titles_array # sacrificing ActiveRecord methods
books.collect { |b| b.titles + b.chapters.collect { |c| c.titles } }
end
您仍然可以对 titles_array.first.author
等单个数组元素使用 AR 方法