Saltar al contenido

Ruby on Rails – ¿Referencia al mismo modelo dos veces?

Te doy la bienvenida a nuestra página, ahora hallarás la respuesta que buscabas.

Solución:

Aquí hay una respuesta completa a este problema, en caso de que las personas que visiten esta pregunta sean nuevas en Ruby on Rails y tengan dificultades para armar todo (como me pasó cuando investigué esto por primera vez).

Algunas partes de la solución tienen lugar en sus Migraciones y otras en sus Modelos:

Migraciones

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

Aquí está especificando que hay dos columnas en esta tabla a las que se hará referencia como: remitente y: destinatario y que contienen referencias a otra tabla. Rails realmente creará columnas llamadas 'sender_id' y 'recipient_id' para usted. En nuestro caso, cada una de ellas hará referencia a filas en la tabla Usuarios, pero lo especificamos en los modelos, no en las migraciones.

Modelos

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

Aquí está creando una propiedad en el modelo PrivateMessage llamado :sender, luego especificando que esta propiedad está relacionada con la clase User. Rails, al ver "belongs_to:sender", buscará una columna en su base de datos llamada "sender_id", que definimos anteriormente, y la usará para almacenar el foráneo key. Entonces estás haciendo exactamente lo mismo para el destinatario.

Esto le permitirá acceder a su remitente y destinatario, ambas instancias del modelo de usuario, a través de una instancia del modelo PrivateMessage, así:

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

Aquí está su modelo de usuario:

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

Aquí está creando una propiedad en el modelo de usuario denominada :sent_private_messages, especificando que esta propiedad está relacionada con el modelo de mensaje privado y que el mensaje externo key en el modelo PrivateMessage que lo relaciona con esta propiedad se llama 'sender_id'. Entonces estás haciendo lo mismo con los mensajes privados recibidos.

Esto le permite hacer que todos los usuarios envíen o reciban mensajes privados haciendo algo como esto:

@user.sent_private_messages
@user.received_private_messages

Hacer cualquiera de estos devolverá un array de instancias del modelo PrivateMessage.

....

Agregue esto a su modelo

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

Y eres capaz de llamar @message.sender y @message.recipient y ambos hacen referencia al modelo de usuario.

En vez de user:references en su comando de generación, necesitaría sender:references y recipient:references

hola, para que la relación de ambos lados haga lo siguiente en ambos 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 esto te ayude...

Puedes confirmar nuestra misión añadiendo un comentario o valorándolo te lo agradecemos.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *