Подтвердить что ты не робот

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

Любой совет будет принята с благодарностью.

Благодарю.

4b9b3361

Ответ 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 эшафот?

Спасибо за ваше время.