Ruby on rails - 两次引用同一个模型?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2057210/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Ruby on rails - Reference the same model twice?
提问by Dan
Is it possible to set up a double relationship in activerecordmodels via the generate scaffoldcommand?
是否可以activerecord通过generate scaffold命令在模型中建立双重关系?
For example, if I had a Usermodel and a PrivateMessagemodel, the private_messages table would need to keep track of both the senderand recipient.
例如,如果我有一个User模型和一个PrivateMessage模型,private_messages 表将需要同时跟踪sender和recipient。
Obviously, for a single relationship I would just do this:
显然,对于单一关系,我会这样做:
ruby script/generate scaffold pm title:string content:string user:references
Is there a similar way to set up two relations?
有没有类似的方法来建立两个关系?
Also, is there anyway to set up aliases for the relations?
另外,无论如何要为关系设置别名?
So rather than saying:
所以与其说:
@message.user
You can use something like:
你可以使用类似的东西:
@message.senderor @message.recipient
@message.sender或者 @message.recipient
Any advice would be greatly appreciated.
任何建议将不胜感激。
Thanks.
谢谢。
回答by Richard Jones
Here's a complete answer to this issue, in case people visiting this question are new to Ruby on Rails and having a hard time putting everything together (as I was when I first looked into this).
这是这个问题的完整答案,以防访问这个问题的人是 Ruby on Rails 的新手并且很难把所有东西放在一起(就像我第一次研究这个问题时一样)。
Some parts of the solution take place in your Migrations and some in your Models:
解决方案的某些部分发生在您的迁移中,有些发生在您的模型中:
Migrations
迁移
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
Here you are specifying that there are two columns in this table that will be referred to as :sender and :recipient and which hold references to another table. Rails will actually create columns called 'sender_id' and 'recipient_id' for you. In our case they will each reference rows in the Users table, but we specify that in the models, not in the migrations.
在这里,您指定该表中有两列将被称为 :sender 和 :recipient 并保存对另一个表的引用。Rails 实际上会为您创建名为“sender_id”和“recipient_id”的列。在我们的例子中,他们将每个引用用户表中的行,但我们在模型中指定,而不是在迁移中。
Models
楷模
class PrivateMessage < ActiveRecord::Base
belongs_to :sender, :class_name => 'User'
belongs_to :recipient, :class_name => 'User'
end
Here you are creating a property on the PrivateMessage model named :sender, then specifying that this property is related to the User class. Rails, seeing the "belongs_to :sender", will look for a column in your database called "sender_id", which we defined above, and use that to store the foreign key. Then you're doing the exact same thing for the recipient.
在这里,您将在 PrivateMessage 模型上创建一个名为 :sender 的属性,然后指定该属性与 User 类相关。Rails 看到“belongs_to :sender”,将在您的数据库中查找我们在上面定义的名为“sender_id”的列,并使用它来存储外键。然后,您正在为收件人做完全相同的事情。
This will allow you to access your Sender and Recipient, both instances of the User model, through an instance of the PrivateMessage model, like this:
这将允许您通过 PrivateMessage 模型的实例访问您的发件人和收件人,这两个实例都是用户模型的实例,如下所示:
@private_message.sender.name
@private_message.recipient.email
Here is your User Model:
这是您的用户模型:
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
Here you are creating a property on the User Model named :sent_private_messages, specifying that this property is related to the PrivateMessage Model, and that the foreign key on the PrivateMessage model which relates it to this property is called 'sender_id'. Then you are doing the same thing for received private messages.
在这里,您将在名为 :sent_private_messages 的用户模型上创建一个属性,指定此属性与 PrivateMessage 模型相关,并且 PrivateMessage 模型上与此属性相关的外键称为“sender_id”。然后你对收到的私人消息做同样的事情。
This allows you to get all of a users sent or received private messages by doing something like this:
这允许您通过执行以下操作来获取所有用户发送或接收的私人消息:
@user.sent_private_messages
@user.received_private_messages
Doing either of these will return an array of instances of the PrivateMessage model.
执行其中任何一个都将返回 PrivateMessage 模型的实例数组。
....
....
回答by Veger
Add this to your Model
将此添加到您的模型中
has_one :sender, :class_name => "User"
has_one :recipient, :class_name => "User"
And you are able to call @message.senderand @message.recipientand both reference to the User model.
并且您可以调用@message.sender和@message.recipient都引用 User 模型。
Instead of user:referencesin your generate command you'd need sender:referencesand recipient:references
而不是user:references在您的 generate 命令中,您需要sender:references和recipient:references
回答by radmehr
hi there to have both side relation do as bellow in your both models:
您好,在您的两个模型中,双方的关系如下:
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
I hope this help you...
我希望这能帮助你...
回答by bbengfort
The above answers, while excellent, do not create foreign key constraints in the database, instead only creating indexes and bigint columns. To ensure that the foreign key constraint is enforced, add the following to your migration:
上述答案虽然出色,但并未在数据库中创建外键约束,而仅创建索引和 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
This will ensure that the indices get created on the sender_idand recipient_idas well as the foreign key constraints in the database you're using.
这将确保在您使用的数据库中的sender_id和recipient_id以及外键约束上创建索引。

