Ruby on rails - Ссылка на ту же модель в два раза?
Можно ли установить двойные отношения в моделях activerecord
с помощью команды generate scaffold
?
Например, если бы у меня была модель User
и модель PrivateMessage
, таблица private_messages должна была бы отслеживать как sender
, так и recipient
.
Очевидно, что для одного отношения я бы просто сделал это:
ruby script/generate scaffold pm title:string content:string user:references
Есть ли похожий способ установить два отношения?
Кроме того, есть ли возможность настроить псевдонимы для отношений?
Так что вместо того, чтобы говорить:
@message.user
Вы можете использовать что-то вроде:
@message.sender
или @message.recipient
Любой совет будет принята с благодарностью.
Благодарю.
Ответы
Ответ 1
Добавьте это в свою модель
has_one :sender, :class_name => "User"
has_one :recipient, :class_name => "User"
И вы можете вызвать @message.sender
и @message.recipient
и обе ссылки на модель пользователя.
Вместо user:references
в вашей команде генерации вам понадобятся sender:references
и recipient:references
Ответ 2
Вот полный ответ на этот вопрос, в случае, если люди, посещающие этот вопрос, являются новичками в 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
Здесь вы указываете, что в этой таблице есть два столбца, которые будут называться: отправитель и: получатель и которые содержат ссылки на другую таблицу. Rails фактически создаст для вас столбцы с именами 'sender_id' и 'receient_id'. В нашем случае они будут ссылаться на строки в таблице Users, но мы указываем это в моделях, а не в миграциях.
модели
class PrivateMessage < ActiveRecord::Base
belongs_to :sender, :class_name => 'User'
belongs_to :recipient, :class_name => 'User'
end
Здесь вы создаете свойство в модели PrivateMessage с именем: sender, а затем указываете, что это свойство связано с классом User. Rails, увидев "own_to: sender", будет искать в вашей базе данных столбец с именем "sender_id", который мы определили выше, и использовать его для хранения внешнего ключа. Тогда вы делаете то же самое для получателя.
Это позволит вам получить доступ к вашему Отправителю и Получателю, оба экземпляра модели User, через экземпляр модели PrivateMessage, например так:
@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.
....
Ответ 3
привет там
чтобы оба боковых отношения делали так, как показано ниже, в обеих моделях:
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
Я надеюсь, что это поможет вам...
Ответ 4
Приведенные выше ответы, хотя и превосходны, не создают ограничений внешнего ключа в базе данных, а создают только индексы и столбцы 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
, а также ограничения внешнего ключа в используемой базе данных.
Ответ 5
Итак... могу ли я сделать то же самое через Rails g эшафот?
Спасибо за ваше время.