Pergunta

É possível configurar um duplo relacionamento em activerecord modelos via generate scaffold comando?

Por exemplo, se eu tivesse um User modelo e a PrivateMessage modelo, a tabela PM precisaria acompanhar os dois sender e recipient.

Obviamente, para um único relacionamento, eu faria isso:

ruby script/generate scaffold pm title:string content:string user:references

Existe uma maneira semelhante de estabelecer duas relações?

Além disso, existe de qualquer maneira para configurar aliases para as relações?

Então, em vez de dizer:

@message.user

Você pode usar algo como:

@message.sender ou @message.recipient

Qualquer conselho seria muito apreciado.

Obrigado.

Foi útil?

Solução

Adicione isso ao seu modelo

has_one :sender, :class_name => "User"
has_one :recipient, :class_name => "User"

E você é capaz de ligar @message.sender e @message.recipient e ambas as referências ao modelo de usuário.

Ao invés de user:references No seu comando de geração, você precisaria sender:references e recipient:references

Outras dicas

Aqui está uma resposta completa a esse problema, caso as pessoas que visitem essa pergunta sejam novas no Ruby on Rails e tenham dificuldade em reunir tudo (como eu estava quando eu olhei para isso pela primeira vez).

Algumas partes da solução ocorrem em suas migrações e outras em seus modelos:

Migrações

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

Aqui você está especificando que existem duas colunas nesta tabela que serão chamadas de: remetente e: destinatário e que mantêm referências a outra tabela. Na verdade, os Rails criarão colunas chamadas 'sender_id' e 'receptor_id' para você. No nosso caso, cada uma delas referenciará linhas na tabela de usuários, mas especificamos que nos modelos, não nas migrações.

Modelos

class PrivateMessage < ActiveRecord::Base
  belongs_to :sender, :class_name => 'User'
  belongs_to :recipient, :class_name => 'User'
end

Aqui você está criando uma propriedade no modelo privatemessage chamado: remetente e, em seguida, especificando que esta propriedade está relacionada à classe de usuário. Os Rails, vendo o "pertencente_to: remetente", procurarão uma coluna no seu banco de dados chamado "sender_id", que definimos acima, e usará isso para armazenar a chave estrangeira. Então você está fazendo exatamente a mesma coisa para o destinatário.

Isso permitirá que você acesse seu remetente e destinatário, ambas as instâncias do modelo de usuário, por meio de uma instância do modelo privatemessage, como este:

@private_message.sender.name
@private_message.recipient.email

Aqui está o seu modelo de usuário:

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

Aqui você está criando uma propriedade no modelo de usuário chamado: Sent_private_messages, especificando que essa propriedade está relacionada ao modelo privatemessage e que a chave estrangeira no modelo privatemessage que o relaciona a esta propriedade é chamada de 'sender_id'. Então você está fazendo a mesma coisa por mensagens privadas recebidas.

Isso permite que você receba todos os usuários ou recebidos mensagens privadas fazendo algo assim:

@user.sent_private_messages
@user.received_private_messages

Fazer qualquer um deles retornará uma variedade de instâncias do modelo privatemessage.

....

Olá, para ter a relação de ambos os laterais, faça o que está abaixo nos dois modelos:

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

Espero que isso lhe ajude...

As respostas acima, embora excelentes, não criam restrições de chave estrangeira no banco de dados, apenas criando apenas índices e colunas BIGINT. Para garantir que a restrição de chave estrangeira seja aplicada, adicione o seguinte à sua migração:

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

Isso garantirá que os índices sejam criados no sender_id e recipient_id bem como as restrições de chave estrangeira no banco de dados que você está usando.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top