Migrazione di Rails: t. Riferimenti con un nome alternativo?


121

Quindi ho una create_table come questa per i corsi presso una scuola:

create_table :courses do |t|
  t.string :name
  t.references :course
  t.timestamps
end

ma voglio che faccia riferimento ad altri due corsi come:

has_many :transferrable_as # A Course
has_many :same_as          # Another Course

Posso dire quanto segue?

t.references :transferrable_as, :as=> :course

Risposte:


161

Puoi fare tutto questo nella migrazione iniziale / definizione della colonna (almeno attualmente in Rails 5):

t.references :transferable_as, index: true, foreign_key: {to_table: :courses}
t.references :same_as, index: true, foreign_key: {to_table: :courses}

10
Funziona su Rails 5.1 e nessuno degli altri suggerimenti funziona. È molto più pulito e sembra giusto.
stephenmurdoch

2
Uso Rails 5.1.4 ma non funziona. Quando specifico foreign_keyun'opzione nella creazione della tabella in questo modo, viene generato un errore che dice che la stessa tabella che sto creando non esiste ... Quindi sospetto che non sia realmente supportata dall'API ufficiale.
Quv

3
Ho anche letto che indexè già stato aggiunto alle chiavi esterne a partire da Rails stackoverflow.com/questions/39769981/…
Jonathan Reyes

98

Puoi farlo in questo modo:

create_table :courses do |t|
  t.string :name
  t.references :transferrable_as
  t.references :same_as
  t.timestamps
end

o utilizzando t.belongs_tocome alias pert.references

Non puoi aggiungere foreign_key: truea queste due linee di riferimento. Se vuoi contrassegnarli come chiavi esterne a livello di database devi avere una migrazione con questo:

add_foreign_key :courses, :courses, column: :transferrable_as_id
add_foreign_key :courses, :courses, column: :same_as_id

Aggiornare

In Rails 5.1 e versioni successive puoi aggiungere la chiave esterna nella migrazione nel create_tableblocco in questo modo:

create_table :courses do |t|
  t.string :name
  t.references :transferrable_as, foreign_key: { to_table: 'courses' }
  t.references :same_as, foreign_key: { to_table: 'courses' }
  t.timestamps
end

5
La parte di non essere in grado di aggiungere foreign_key: truealle linee di riferimento era ciò che mi faceva inciampare. Aggiungere add_foreign_keye specificare il nome della colonna per quelli ha funzionato.
Matthew Clark

Funziona fuori dagli schemi in Rails? Secondo stackoverflow.com/a/22384289/239657 , questo richiede la schema_plusgemma. I documenti add_reference di Rails non menzionano le opzioni a: references.
Beni Cherniavsky-Paskin

1
Non sto seguendo a cosa references:serve l' opzione (al contrario di t.referencesciò che non sarebbe rilevante solo a livello di modello, con le considerazioni foreign_key di cui si prende cura add_foreign_key?
MCB

1
@MCB t.referencesdice "aggiungi un campo a questa tabella che è la chiave primaria di un'altra tabella". L' references:opzione gli dice di quale tabella è una chiave primaria (necessaria se non è chiara dal nome del campo). La add_foreign_keyfunzione indica al database di applicare l'integrità referenziale qui.
Toby 1 Kenobi

2
@ MCB dopo tutto questo tempo mi rendo conto che avevi ragione fin dall'inizio. Il tuo primo commento sopra è esattamente corretto: le add_foreign_keyrighe si occupano di informare il database che cos'è una chiave esterna di cosa. Il references:parametro non fa nulla.
Toby 1 Kenobi

13

Penso che questo thread abbia un modo diverso e più Rails: Scaffolding ActiveRecord: due colonne dello stesso tipo di dati

Nella migrazione:

t.belongs_to: transferrable_as

t.belongs_to: same_as


1
ma come fa il db a sapere a quale chiave esterna collegare la tabella? Lo sto provando con il database Postgres e mi dà un errore PG::UndefinedTable: ERRORnel tentativo di aggiungere un vincolo di chiave esterna a una tabella che non esiste.
Toby 1 Kenobi

Nel caso qualcuno se lo stesse chiedendo, belongs_toè solo un alias di referencese quindi ha la stessa identica funzionalità.
Jason Swett

11

Come risposta aggiuntiva a questa domanda, il Modello dovrebbe avere la seguente riga per completare l'associazione:

    belongs_to :transferrable_as, class_name: "Course"
    belongs_to :same_as, class_name: "Course"

3

Non penso referencesaccetti l' :asopzione, ma puoi creare le tue colonne manualmente ...

create_table :courses do |t| 
  t.string  :name 
  t.integer :course1_id
  t.integer :course2_id 
  t.timestamps 
end 
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.