through references rails has_one has_many has_and_belongs_to_many example create active ruby-on-rails rails-activerecord relationships

ruby-on-rails - has_one - rails model references



Ruby on rails: ¿hace referencia al mismo modelo dos veces? (4)

¿Es posible establecer una doble relación en los modelos activerecord través del comando generate scaffold ?

Por ejemplo, si tuviera un modelo de User y un modelo de PrivateMessage , la tabla pm necesitaría hacer un seguimiento tanto del sender como del recipient .

Obviamente, para una relación única, simplemente haría esto:

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

¿Hay alguna manera similar de establecer dos relaciones?

Además, ¿hay alguna forma de configurar alias para las relaciones?

Entonces, en lugar de decir:

@message.user

Puedes usar algo como:

@message.sender o @message.recipient

Cualquier consejo sería muy apreciado.

Gracias.


Agregue esto a su modelo

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

Y puede llamar a @message.sender y @message.recipient y a ambas referencias al modelo de Usuario.

En lugar de user:references en tu comando de generación necesitarías sender:references y recipient:references


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 unir todo (como yo lo hice cuando analicé esto por primera vez).

Algunas partes de la solución tienen lugar en sus Migraciones y algunas 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í especifica 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 en realidad creará columnas llamadas ''sender_id'' y ''recipient_id'' por usted. En nuestro caso, cada una de ellas hará referencia a las 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 de PrivateMessage llamado: sender, y luego especifica 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 la clave externa. 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 de PrivateMessage, como esta:

@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 llamado: send_private_messages, especificando que esta propiedad está relacionada con el Modelo PrivateMessage, y que la clave externa 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 obtener todos los usuarios enviados o recibidos mensajes privados haciendo algo como esto:

@user.sent_private_messages @user.received_private_messages

Hacer cualquiera de estos devolverá una matriz de instancias del modelo de PrivateMessage.

....


Las respuestas anteriores, aunque son excelentes, no crean restricciones de clave externa en la base de datos, sino que solo crean índices y columnas bigint. Para garantizar el cumplimiento de la restricción de clave externa, agregue lo siguiente a su migración:

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

Esto asegurará que los índices se creen en sender_id y recipient_id , así como en las restricciones de clave externa en la base de datos que está utilizando.


hola para tener ambas relaciones secundarias haz lo siguiente en tus dos 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...