genera il modello usando user: references vs user_id: integer


177

Sono confuso su come generare un modello che appartiene a un altro modello. Il mio libro usa questa sintassi per associare Micropost con l'utente:

rails generate model Micropost user_id:integer

ma http://guides.rubyonrails.org/ dice di farlo in questo modo:

rails generate model Micropost user:references

Le migrazioni generate da questi 2 sono diverse. Inoltre, per il primo, come fa a sapere che le rotaie user_idsono riferimenti a una chiave esterna user? Grazie!

Risposte:


190

Entrambi genereranno le stesse colonne quando si esegue la migrazione. Nella console di rotaie, puoi vedere che è così:

:001 > Micropost
=> Micropost(id: integer, user_id: integer, created_at: datetime, updated_at: datetime)

Il secondo comando aggiunge una belongs_to :userrelazione nel modello Micropost mentre il primo no. Quando viene specificata questa relazione, ActiveRecord supporrà che la chiave esterna sia mantenuta nella user_idcolonna e utilizzerà un modello denominato Userper creare un'istanza dell'utente specifico.

Il secondo comando aggiunge anche un indice sulla nuova user_idcolonna.


1
È possibile generare un modello con riferimenti di due tabelle
praveenkumar l'

Nota che non aggiunge un'associazione has_many sull'altro modello (utente), che potresti voler aggiungere.
Sv1,

45

come fanno i binari a sapere che user_idè un riferimento a chiave esterna user?

Rails stesso non sa che si user_idtratta di un riferimento a chiave esterna user. Nel primo comando rails generate model Micropost user_id:integeraggiunge solo una colonna user_idma le rotaie non conoscono l'uso del col. Devi inserire manualmente la linea nel Micropostmodello

class Micropost < ActiveRecord::Base
  belongs_to :user
end

class User < ActiveRecord::Base
  has_many :microposts
end

le parole chiave belongs_toe has_manydeterminare la relazione tra questi modelli e dichiarare user_idcome chiave esterna per il Usermodello.

Il comando successivo rails generate model Micropost user:referencesaggiunge la linea belongs_to :usernel Micropostmodello e dichiara come chiave esterna.

FYI
Dichiarare le chiavi esterne usando il metodo precedente fa conoscere a Rails solo la relazione che hanno i modelli / le tabelle. Il database non è noto sulla relazione. Pertanto, quando si generano i diagrammi EER utilizzando un software come quello, MySql Workbenchsi scopre che non ci sono discussioni di relazione tra i modelli. Come nella foto seguente inserisci qui la descrizione dell'immagine

Tuttavia, se si utilizza il metodo successivo, si scopre che il file di migrazione è simile al seguente:

def change
    create_table :microposts do |t|
      t.references :user, index: true

      t.timestamps null: false
    end
    add_foreign_key :microposts, :users

Ora la chiave esterna è impostata a livello di database. e puoi generare EERdiagrammi adeguati . inserisci qui la descrizione dell'immagine


1
Sembra che l'ultimo generatore di Rails abbia sostituito l' add_foreign_keyazione con un'opzione foreign_key: truealla t.referenceslinea, il che implica index: true. Così è adesso t.references :user, foreign_key: true. Al momento non è disponibile alcuna documentazione per l' foreign_keyopzione disponibile, quindi questa è solo la mia ipotesi.
Franklin Yu,

Oh, l' add_referenceazione ha :foreign_keyun'opzione che aggiunge un vincolo di chiave esterna appropriato . Immagino che questa opzione farebbe lo stesso durante la creazione della tabella.
Franklin Yu,

Come esportate il vostro ruby ​​db nel workbench? si potrebbe forse rispondere a questa qui: stackoverflow.com/questions/42982921/...
Krawalla

Avere add_foreign_key :microposts, :users qualche differenza per Rails?
Linus,

17

Per il primo, convenzione sulla configurazione. Rotaie predefinite quando si fa riferimento a un'altra tabella con

 belongs_to :something

è cercare something_id.

references, o belongs_toè in realtà un modo più nuovo di scrivere il primo con poche stranezze.

È importante ricordare che non creerà chiavi esterne per te. Per fare ciò, è necessario configurarlo esplicitamente usando:

t.references :something, foreign_key: true
t.belongs_to :something_else, foreign_key: true

oppure (notare il plurale):

add_foreign_key :table_name, :somethings
add_foreign_key :table_name, :something_elses`

1
puoi spiegare cosa intendi dicendo che i riferimenti non creeranno chiavi esterne per te. In che modo differisce dal primo comando usando user_id: intero direttamente?
Shailesh,

Non lo è, tranne nel caso in cui si stia utilizzando l' :polymorphicopzione (che IMHO, nella maggior parte dei casi, non è una buona idea). Se si desidera utilizzare chiavi esterne in ActiveRecord, utilizzare straniero .
Krule il

1
@Krule Now add_foreign_keyè diventato ActiveRecord.
Franklin Yu,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.