首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如果涉及多态关联,如何创建“has_many通过”关联?

如果涉及多态关联,如何创建“has_many通过”关联?
EN

Stack Overflow用户
提问于 2015-12-30 10:55:15
回答 2查看 232关注 0票数 1

我有4个模型:模型1与模型2相关联,模型2与模型3相关联,模型2和模型3与模型4相关联。这一切都有效。我在指定模型1和模型4之间的关联时遇到了困难,因此,模型1和模型4之间有两种关联:

  1. 模型1-模型2-模型4
  2. 模型1-模型2-模型3-模型4

下面将找到所有的关联,除了模型1和模型4之间的关联:

作者模型:

代码语言:javascript
复制
has_many :books,     dependent: :destroy

图书模型:

代码语言:javascript
复制
belongs_to :author
has_many   :chapters, dependent: :destroy
has_many   :titles,   as: :titlesource,       # Polymorphic Association
                      dependent: :destroy

章节模式:

代码语言:javascript
复制
belongs_to :book
has_many   :titles,   as: :titlesource,       # Polymorphic Association
                      dependent: :destroy

标题模式:

代码语言:javascript
复制
belongs_to :titlesource, polymorphic: true

问题:假设您有上述关联,并且希望了解author所具有的titles,而不管它们是书名还是章节标题。我应该用什么关联来扩展上面的设置?(我假设是关于has_many through的)

更新:如果它只是我要寻找的书名,我希望将has_many :titles, through: :books添加到Author模型中。但事实并非如此,如果我添加了这个关联,那么Author.first.titles就会产生错误undefined method 'titles'。我认为这与多态关联和命名有关.?我做错了什么?

对于章节标题来说,这就更难了。这个关联通过Book模型,然后通过Chapter模型,然后再到Title模型。如何将这些标题包含在作者模型中?我认为它必须是具有以下逻辑的代码(但很明显,此代码是错误的):

代码语言:javascript
复制
has_many :titles, through: :books && :books:chapters

更新:给出的两个答案使用。这些解决方案是否向数据库发送了大量查询,如果经常使用该方法会导致问题吗?这些方法中的一种在性能上比另一种有优势吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-01-01 23:06:56

如果要在Author上使用像has_many :titles, through: :books这样的关联,那么只要在Title模型迁移中设置了titlesource_idtitlesource_type,它通常就能工作。

但是,如果要添加另一个以通过像这个has_many :titles, through: :chapters这样的章节来获取标题,它将覆盖第一个章节,并且它将只获取属于titlesource_type = 'Chapter'的标题。

因此,如果您不介意sql,我向您建议的解决方案是在Author模型中实现这样的方法。

代码语言:javascript
复制
  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
票数 3
EN

Stack Overflow用户

发布于 2016-01-05 08:28:03

如果您不需要ActiveRecord方法(如whereorder),那么这将为您提供一系列标题。

代码语言:javascript
复制
def titles_array  # sacrificing ActiveRecord methods
  books.collect { |b| b.titles + b.chapters.collect { |c| c.titles } }
end

仍然可以对单个数组元素(如titles_array.first.author等)使用AR方法。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34528094

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档