您如何构造一个 rails 模型,其中两个属性需要与另一个模型共享相同的关联?
How do you structure a rails model where two attributes need to share the same association with another model?
我正在开发一个 Rails 应用程序,它汇集了艺术家对其他艺术家的评价,但我无法弄清楚我的数据模型中的关系应该如何工作。
以这句话为例。以下是 David Bowie 对 Lou Reed 的评价:
"He was a master"
在此示例中,我的 Quote 模型属性如下所示:
- 节选 => "He was a Master"
- 扬声器 => "David Bowie"
- 主题 => "Lou Reed"
但是如果 Lou Reed 说了一些关于 David Bowie 的事情,比如:
- 节选 => "He was my best friend in the 70s"
- 扬声器 => "Lou Reed"
- 主题 => "David Bowie"
一位艺术家既可以是演讲者也可以是引言的主题,但绝不会是同一引语。我还希望用户能够创建新的艺术家,然后在创建报价时将这些显示为与报价相关联的选项(通过下拉菜单或搜索等)。
我似乎无法构建它,使报价通过演讲者有很多艺术家,因为它也可以通过主题有很多艺术家。
这是惯用的 Rails 结构方式吗:
Quote
has_one :speaker
has_one :subject
Speaker
has_many :artists
belongs_to_many :quotes
Subject
has_many :artists
belongs_to_many :quotes
Artist
belongs_to_many :speakers
belongs_to_many :subjects
我相信您希望报价看起来像这样:
class Quote < ActiveRecord::Base
belongs_to :speaker, class_name: "Artist"
belongs_to :subject, class_name: "Artist"
belongs_to :user
validates :speaker, uniqueness: {scope: :subject}
validates :subject, uniqueness: {scope: :speaker}
...
end
假设:
- 一位用户(可能是 current_user 或类似的人)正在创建报价并且该报价属于该用户。
- 艺术家与用户是不同的概念。也就是说,艺术家不一定是用户(引用可能以 David Bowie 作为主题,但 David Bowie 可能不是您系统的用户(特别是考虑到他和 Lou Reed 一样已经去世))。
这样,speaker
和subject
都被指定为classArtist
。
唯一性验证确保 speaker
永远不会是 subject
,反之亦然。 (您可能需要摆弄 validates
语句,因为我没有测试。)
在您的 Artist
模型中,您可能想要执行以下操作:
class Artist < ActiveRecord::Base
has_many :spoken_quotes, class_name: "Quote", foreign_key: :speaker_id
has_many :referencing_quotes, class_name: "Quote", foreign_key: :subject_id
...
end
这样,您可以执行以下操作:
Artist.find_by(name: 'David Bowie').spoken_quotes
并获得所有 Quotes
大卫鲍伊是 speaker
。
并且,在您的 User
模型中,您可能想要这样的东西:
class User < ActiveRecord::Base
has_many: :quotes
...
end
以便您可以执行以下操作:
current_user.quotes
并获取 current_user
创建的所有报价。
假设您有以下架构:
user - id
quote - author_id, subject_id
您可以像这样建立关系,利用这些关联方法可用的选项:
# User
has_many :sent_quotes, class_name: "Quote", foreign_key: :author_id
has_many :received_quotes, class_name: "Quote", foreign_key: :subject_id
has_many :quote_receivers, through: :sent_quotes, source: :subject
has_many :quote_senders, through: :received_quotes, source: :authors
# Quote
belongs_to :author, class_name: "User"
belongs_to :subject, class_name: "User"
我正在开发一个 Rails 应用程序,它汇集了艺术家对其他艺术家的评价,但我无法弄清楚我的数据模型中的关系应该如何工作。
以这句话为例。以下是 David Bowie 对 Lou Reed 的评价:
"He was a master"
在此示例中,我的 Quote 模型属性如下所示:
- 节选 => "He was a Master"
- 扬声器 => "David Bowie"
- 主题 => "Lou Reed"
但是如果 Lou Reed 说了一些关于 David Bowie 的事情,比如:
- 节选 => "He was my best friend in the 70s"
- 扬声器 => "Lou Reed"
- 主题 => "David Bowie"
一位艺术家既可以是演讲者也可以是引言的主题,但绝不会是同一引语。我还希望用户能够创建新的艺术家,然后在创建报价时将这些显示为与报价相关联的选项(通过下拉菜单或搜索等)。
我似乎无法构建它,使报价通过演讲者有很多艺术家,因为它也可以通过主题有很多艺术家。
这是惯用的 Rails 结构方式吗:
Quote
has_one :speaker
has_one :subject
Speaker
has_many :artists
belongs_to_many :quotes
Subject
has_many :artists
belongs_to_many :quotes
Artist
belongs_to_many :speakers
belongs_to_many :subjects
我相信您希望报价看起来像这样:
class Quote < ActiveRecord::Base
belongs_to :speaker, class_name: "Artist"
belongs_to :subject, class_name: "Artist"
belongs_to :user
validates :speaker, uniqueness: {scope: :subject}
validates :subject, uniqueness: {scope: :speaker}
...
end
假设:
- 一位用户(可能是 current_user 或类似的人)正在创建报价并且该报价属于该用户。
- 艺术家与用户是不同的概念。也就是说,艺术家不一定是用户(引用可能以 David Bowie 作为主题,但 David Bowie 可能不是您系统的用户(特别是考虑到他和 Lou Reed 一样已经去世))。
这样,speaker
和subject
都被指定为classArtist
。
唯一性验证确保 speaker
永远不会是 subject
,反之亦然。 (您可能需要摆弄 validates
语句,因为我没有测试。)
在您的 Artist
模型中,您可能想要执行以下操作:
class Artist < ActiveRecord::Base
has_many :spoken_quotes, class_name: "Quote", foreign_key: :speaker_id
has_many :referencing_quotes, class_name: "Quote", foreign_key: :subject_id
...
end
这样,您可以执行以下操作:
Artist.find_by(name: 'David Bowie').spoken_quotes
并获得所有 Quotes
大卫鲍伊是 speaker
。
并且,在您的 User
模型中,您可能想要这样的东西:
class User < ActiveRecord::Base
has_many: :quotes
...
end
以便您可以执行以下操作:
current_user.quotes
并获取 current_user
创建的所有报价。
假设您有以下架构:
user - id
quote - author_id, subject_id
您可以像这样建立关系,利用这些关联方法可用的选项:
# User
has_many :sent_quotes, class_name: "Quote", foreign_key: :author_id
has_many :received_quotes, class_name: "Quote", foreign_key: :subject_id
has_many :quote_receivers, through: :sent_quotes, source: :subject
has_many :quote_senders, through: :received_quotes, source: :authors
# Quote
belongs_to :author, class_name: "User"
belongs_to :subject, class_name: "User"