Domanda

È possibile impostare una doppia relazione in activerecord modelli tramite il generate scaffold comando?

Ad esempio, se avessi un User modello e a PrivateMessage modello, la tabella pm dovrebbe tenere traccia di entrambi i file sender E recipient.

Ovviamente, per una singola relazione farei semplicemente questo:

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

Esiste un modo simile per impostare due relazioni?

Inoltre, è comunque possibile impostare alias per le relazioni?

Quindi invece di dire:

@message.user

Puoi usare qualcosa come:

@message.sender O @message.recipient

Qualsiasi consiglio sarebbe molto apprezzato.

Grazie.

È stato utile?

Soluzione

Aggiungi questo al vostro modello

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

E si è in grado di chiamare @message.sender e @message.recipient ed entrambi riferimento al modello User.

Invece di user:references nel comando generare avresti bisogno sender:references e recipient:references

Altri suggerimenti

Ecco una risposta completa a questo problema, nel caso in cui le persone che visitano questa domanda siano nuove in Ruby on Rails e abbiano difficoltà a mettere tutto insieme (come ho fatto io quando ho esaminato questo problema per la prima volta).

Alcune parti della soluzione si svolgono nelle tue migrazioni e altre nei tuoi modelli:

Migrazioni

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

Qui stai specificando che ci sono due colonne in questa tabella che verranno chiamate :sender e :recipient e che contengono riferimenti a un'altra tabella.Rails creerà effettivamente colonne chiamate 'sender_id' e 'recipient_id' per te.Nel nostro caso ciascuno farà riferimento a righe nella tabella Utenti, ma lo specifichiamo nei modelli, non nelle migrazioni.

Modelli

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

Qui stai creando una proprietà sul modello PrivateMessage denominata :sender, quindi specificando che questa proprietà è correlata alla classe User.Rails, vedendo "belongs_to:sender", cercherà una colonna nel tuo database chiamata "sender_id", che abbiamo definito sopra, e la utilizzerà per memorizzare la chiave esterna.Quindi stai facendo esattamente la stessa cosa per il destinatario.

Ciò ti consentirà di accedere al mittente e al destinatario, entrambe le istanze del modello Utente, attraverso un'istanza del modello PrivateMessage, in questo modo:

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

Ecco il tuo modello utente:

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

Qui stai creando una proprietà sul modello utente denominata :sent_private_messages, specificando che questa proprietà è correlata al modello PrivateMessage e che la chiave esterna sul modello PrivateMessage che la collega a questa proprietà è chiamata 'sender_id'.Quindi stai facendo la stessa cosa per i messaggi privati ​​ricevuti.

Ciò ti consente di inviare o ricevere messaggi privati ​​a tutti gli utenti facendo qualcosa del genere:

@user.sent_private_messages
@user.received_private_messages

Eseguendo una di queste operazioni verrà restituita una serie di istanze del modello PrivateMessage.

....

Ciao avere sia relazione lato fare come muggito nelle vostre entrambi i modelli:

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

Spero che questo aiuto si ...

Le risposte di cui sopra, mentre eccellente, non creano vincoli stranieri chiave nel database, invece solo gli indici che creano e colonne bigint. Per garantire che il vincolo di chiave esterna viene applicata, aggiungere il seguente alla migrazione:

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

Questo farà sì che gli indici vengono creati sul sender_id e recipient_id nonché i vincoli di chiave esterna nel database che si sta utilizzando.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top