generate scaffold
コマンドを使用してactiverecord
モデルに二重の関係を設定することはできますか?
たとえば、User
モデルとPrivateMessage
モデルがある場合、private_messagesテーブルはsender
とrecipient
の両方を追跡する必要があります。
明らかに、単一の関係については、これを行うだけです。
Ruby script/generate scaffold pm title:string content:string user:references
2つの関係を設定する同様の方法はありますか?
また、関係にエイリアスを設定する方法はありますか?
だから言うよりも:
@message.user
あなたは次のようなものを使うことができます:
@message.sender
または@message.recipient
何かアドバイスをいただければ幸いです。
ありがとう。
これをモデルに追加します
has_one :sender, :class_name => "User"
has_one :recipient, :class_name => "User"
また、@message.sender
と@message.recipient
を呼び出すことができ、どちらもUserモデルを参照します。
生成コマンドのuser:references
の代わりに、sender:references
とrecipient:references
が必要になります
この質問にアクセスした人が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と呼ばれ、別のテーブルへの参照を保持する2つの列があることを指定しています。 Railsは実際には「sender_id」と「recipient_id」という列を作成します。この場合、これらはそれぞれUsersテーブルの行を参照しますが、マイグレーションではなくモデルで指定します。
class PrivateMessage < ActiveRecord::Base
belongs_to :sender, :class_name => 'User'
belongs_to :recipient, :class_name => 'User'
end
ここでは、:senderという名前のPrivateMessageモデルにプロパティを作成し、このプロパティがUserクラスに関連していることを指定しています。 Railsは、「belongs_to:sender」を参照して、上記で定義した「sender_id」と呼ばれるデータベース内の列を探し、それを使用して外部キーを格納します。次に、受信者に対してまったく同じことを行います。
これにより、次のように、PrivateMessageモデルのインスタンスを介して、Userモデルの両方のインスタンスであるSenderとRecipientにアクセスできます。
@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モデルのインスタンスの配列が返されます。
....
こんにちは、両方のモデルで次のように両側の関係を実行します。
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
これがお役に立てば幸いです...
上記の回答は優れていますが、データベースに外部キー制約を作成せず、インデックスと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
、および使用しているデータベースの外部キー制約にインデックスが確実に作成されます。