是否可以通过activerecord
命令在generate scaffold
模型中设置双重关系?
例如,如果我有User
模型和PrivateMessage
模型,则pm表需要跟踪sender
和recipient
。
显然,对于单一的关系,我会这样做:
ruby script/generate scaffold pm title:string content:string user:references
是否有类似的方式来建立两种关系?
另外,有没有为关系设置别名?
所以不要说:
@message.user
您可以使用以下内容:
@message.sender
或@message.recipient
非常感谢任何建议。
感谢。
答案 0 :(得分:113)
以下是这个问题的完整答案,如果访问此问题的人不熟悉Ruby on Rails并且很难将所有内容放在一起(就像我第一次看到这个时一样)。
解决方案的某些部分发生在您的迁移中,而某些部分发生在您的模型中:
class CreatePrivateMessages < ActiveRecord::Migration
def change
create_table :private_messages do |t|
t.references :sender
t.references :recipient
end
# Rails 5+ only: add foreign keys
add_foreign_key :private_messages, :users, column: :sender_id, primary_key: :id
add_foreign_key :private_messages, :users, column: :recipient_id, primary_key: :id
end
end
此处指定此表中有两列将被称为:sender和:recipient,它们包含对另一个表的引用。 Rails实际上会为您创建名为“sender_id”和“recipient_id”的列。在我们的例子中,他们将每个引用Users表中的行,但我们在模型中指定,而不是在迁移中。
class PrivateMessage < ActiveRecord::Base
belongs_to :sender, :class_name => 'User'
belongs_to :recipient, :class_name => 'User'
end
这里,您要在PrivateMessage模型上创建一个名为:sender的属性,然后指定此属性与User类相关。看到“belongs_to:sender”的Rails将在数据库中查找名为“sender_id”的列,我们在上面定义了该列,并使用它来存储外键。那么你正在为收件人做同样的事情。
这将允许您通过PrivateMessage模型的实例访问您的发件人和收件人(User模型的两个实例),如下所示:
@private_message.sender.name
@private_message.recipient.email
以下是您的用户模型:
class User < ActiveRecord::Base
has_many :sent_private_messages, :class_name => 'PrivateMessage', :foreign_key => 'sender_id'
has_many :received_private_messages, :class_name => 'PrivateMessage', :foreign_key => 'recipient_id'
end
在这里,您要在用户模型上创建一个名为:sent_private_messages的属性,指定此属性与PrivateMessage模型相关,并且PrivateMessage模型上与此属性相关的外键称为“sender_id”。然后,您正在为收到的私人消息做同样的事情。
这允许您通过执行以下操作来让所有用户发送或接收私人消息:
@user.sent_private_messages
@user.received_private_messages
执行其中任何一项操作都将返回PrivateMessage模型的实例数组。
...
答案 1 :(得分:56)
将此添加到您的模型
has_one :sender, :class_name => "User"
has_one :recipient, :class_name => "User"
您可以致电@message.sender
和@message.recipient
,并且都引用用户模型。
您的生成命令中不需要user:references
,而是需要sender:references
和recipient:references
答案 2 :(得分:17)
你好 在两个模型中都有两个侧面关系:
class Message < ActiveRecord::Base
belongs_to :sender,
:class_name => "User",
:foreign_key => "sender_id"
belongs_to :recipient,
:class_name => "User",
:foreign_key => "recipient_id"
end
class User < ActiveRecord::Base
has_many :sent,
:class_name => "Message",
:foreign_key => "sent_id"
has_many :received,
:class_name => "Message",
:foreign_key => "received_id"
end
我希望这可以帮助你...
答案 3 :(得分:8)
上述答案虽然很好,但不会在数据库中创建外键约束,而只会创建索引和bigint列。要确保强制实施外键约束,请将以下内容添加到迁移中:
class CreatePrivateMessages < ActiveRecord::Migration[5.1]
def change
create_table :private_messages do |t|
t.references :sender
t.references :recipient
end
add_foreign_key :private_messages, :users, column: :sender_id, primary_key: :id
add_foreign_key :private_messages, :users, column: :recipient_id, primary_key: :id
end
end
这将确保在sender_id
和recipient_id
上创建索引以及您正在使用的数据库中的外键约束。