【问题标题】:Rails association has_many and has_many through on same STI modelRails 关联 has_many 和 has_many 通过相同的 STI 模型
【发布时间】:2017-01-26 00:29:16
【问题描述】:

我有一个模型笔记。 注释非常有用,并且在整个应用程序中用于多种用途。

我们有另一个模型用户,这些是 STI 之间的拆分 用户1s 和 用户2s

我们有第三个模型 Thing,它是属于用户的东西......我暂时把它留在那里,因为它变得更复杂了,(还有其他模型有点像 Things 也可以制作注释)。

Note.rb
belongs_to :user #This signifies that the user wrote the note
belongs_to :notable, polymorphic: :true #This is what the note is referring to

User.rb
has_many :user_notes, class_name: "Note", foreign_key: "user_id" 
#signifies the note was written by the User

User1.rb < User
has_many :notes, as: :notable 
#Signifies the note was about the User1
has_many :things

User2.rb < User
has_many :notes, as: :notable 
#Signifies the note was about the User2


Thing.rb
belongs_to :user1
has_many :notes, as: :notable 
#The note is about the thing

这些可以是,但通常不是,自我参照(我写了一个关于我自己的笔记)。

通常用户1会写关于用户2的注​​释,或者关于用户2的事情,以便用户2可以看到它们。

我认为我在重命名 user_notes 时采取了正确的方法。

我正在为如何收集所有可能与我有关的笔记而苦恼。 即假设我是用户1。 我想看看我写的笔记,还有其他人写的关于我的笔记,还有关于我的东西的笔记。

有没有简单的方法可以做到这一点? 我在两点上苦苦挣扎。

  1. 如何连接关于我的东西的笔记?

    has_many :thing_notes,通过::things,来源::notes

有效,但我想知道这是否是接近它的正确方法。

另外,我对反向感兴趣(这也有点用),在这种情况下,忽略可能写了注释的人,返回相关的 user1,如果有的话。但是……

delegate :user1, to: :notable

如果 user1 已经是潜在的 notable_type 则没有意义。

  1. 我如何整理我的所有笔记(无论是什么类型的)并归还它们?

@user1.notes 

将只返回关于我的笔记

@user1.user_notes 

将返回我写的笔记

@user1.thing_notes 

将返回有关我的东西的注释

我可以将它们合并在一起,但我会冒着出现烦人的重复的风险,而且当它们都是一种类型时,进行多个数据库调用并丢失数据库排序似乎是一种耻辱......

有没有明显的方法来获取我的所有笔记...?

Note.where("(user_id = :user1_id) OR (notable_id = :user1_id AND notable_type = 'User') OR (notable_type = 'Thing' AND notable_id IN (:things))", user1_id: user1.id, things:user1.thing_ids)

有点丑陋的一面,只会变得更丑陋......

希望对喜欢解决此类难题的人有意义...

【问题讨论】:

  • 有没有理由不用Thingbelongs_to :user 而不是user1
  • 从系统逻辑的角度来看,是的。 User2s没有东西。 (虽然他们确实有thing2s和thing3s,为了争论)。

标签: ruby-on-rails associations polymorphic-associations sti


【解决方案1】:

对于排序规则,如果您使用的是 Rails 5,则可以执行以下操作来简化原始 SQL:

Note.where(user: user1).or(Note.where(notable: user1)).or(Note.where(notable: user1.things))

如果您不使用 Rails 5,您可以包含此 gem 以实现相同的功能:https://github.com/Eric-Guo/where-or

【讨论】:

  • 还不打算升级到 Rails 5。需要尽可能避免这种痛苦。我去看看那个宝石。当然使查询更清晰。那么问题是您如何建议使用该查询。有没有办法明智地将其与 activerecord 或范围集成?或者只是将它作为 User1 上的实例方法?或者也许是笔记上的类方法/范围,然后递归调用它。我正在考虑放置范围,以便我可以拥有 .all_notes 或 .notes_about_me(不包括我写的与我无关的笔记)。
  • 如果你想在某个时候单独访问它们,那么范围是有意义的。它们可以用作实例方法。
猜你喜欢
  • 2014-12-16
  • 2017-01-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多