Migrazioni di Rails 3: aggiunta della colonna di riferimento?


162

Se creo una nuova migrazione di rails 3 con (ad esempio)

rails g migration tester title:tester user:references

, tutto funziona bene ... tuttavia se aggiungo una colonna con qualcosa lungo le righe di:

rails g migration add_user_to_tester user:references

il campo di riferimento non è riconosciuto. In breve, la domanda è: come posso aggiungere una colonna di riferimento a una migrazione di rotaie dalla riga di comando?

Risposte:


205

Se stai utilizzando Rails 4.x ora puoi generare migrazioni con riferimenti, in questo modo:

rails generate migration AddUserRefToProducts user:references

come puoi vedere sulle guide dei binari



2
come si specifica un nome di colonna per la chiave esterna anziché il nome generato automaticamente?
j

@jwill puoi usare polimorfico: utente: riferimenti {polimorfico}.
Paulo Fidalgo, l'

@PauloFidalgo Puoi spiegarci un po 'come farlo? potrebbe essere una guida di link? (parlando di polimorfico)
Anwar,


186

EDIT : questa è una risposta obsoleta e non deve essere applicata per Rails 4.x +

Non è necessario aggiungere riferimenti quando è possibile utilizzare un ID intero per la classe di riferimento.

Direi che il vantaggio di usare i riferimenti invece di un semplice numero intero è che il modello sarà predefinito con appartiene_to e poiché il modello è già stato creato e non sarà influenzato quando si migra qualcosa esistente, lo scopo è in qualche modo perso.

Quindi vorrei fare questo invece:

rails g migration add_user_id_to_tester user_id:integer

Quindi aggiungere manualmente appartiene_to: utente nel modello Tester


9
Ma ciò non creerà i vincoli di chiave esterna appropriati sui database che lo supportano, giusto?
abahgat,

19
No, afaik Rails non crea mai restrizioni di chiave esterna sul database a meno che non si aggiungano plug-in per farlo.
DanneManne,

sto solo studiando questo post, per favore come posso aggiungere il riferimento dopo tutto
El nino

13
ricordati di aggiungere l'indice con l'utente: intero: indice
rickypai

3
La risposta è datata, vedi la risposta di @ Paulo per i binari moderni.
OneHoopyFrood

102

Tieni presente che molto probabilmente avrai bisogno di un indice anche su quella colonna.

class AddUserReferenceToTester < ActiveRecord::Migration
  def change
    add_column :testers, :user_id, :integer
    add_index  :testers, :user_id
  end
end

1
Perché? Questo è vero per la maggior parte delle relazioni?
ahnbizcad,

È in effetti per motivi di prestazioni ed è utile se hai un has_many / has_one dall'altra parte di quella relazione relazione. Se sei assolutamente sicuro di non passare user.testers, puoi omettere l'indice.
Eugene,

1
Il rails g migration ...generato add_reference :installs, :device, index: trueche crea anche l'indice.
B Sette,

49

Con i due passaggi precedenti indicati in precedenza, ti manca ancora il vincolo di chiave esterna. Questo dovrebbe funzionare:

  class AddUserReferenceToTester < ActiveRecord::Migration
      def change
          add_column :testers, :user_id, :integer, references: :users
      end
  end

Questa è l'unica vera risposta qui. La chiave esterna è la parte più critica qui
user2490003

questa dovrebbe essere contrassegnata come la risposta corretta poiché le domande richiedono rotaie 3
Carlos Roque

35

È possibile utilizzare i riferimenti in una migrazione di modifica. Questo è il codice Rails 3.2.13 valido:

class AddUserToTester < ActiveRecord::Migration
  def change
    change_table :testers do |t|
      t.references :user, index: true 
    end
  end
  def down
    change_table :testers do |t|
      t.remove :user_id
    end
  end
end

cf: http://apidock.com/rails/ActiveRecord/ConnectionAdapters/SchemaStatements/change_table


1
cambia e abbassa i metodi? non sono invece i metodi su e giù?
MaicolBen,

@MaicolBen sì, e puoi anche lasciare il metodo down.
Hut8

@MaicolBen Senza il downmetodo, ho ottenuto eseguendo il ActiveRecord::IrreversibleMigrationrollback utilizzando Rails 3.2. Ho anche dovuto cambiare changea up.
Andrew Grimm

27

L'esecuzione rails g migration AddUserRefToSponsors user:referencesgenererà la seguente migrazione:

def change
  add_reference :sponsors, :user, index: true
end

Per quale versione di Rails si tratta?
Andrew Grimm

8

Quando si aggiunge una colonna, è necessario rendere tale colonna un numero intero e, se possibile, attenersi alle convenzioni delle rotaie. Quindi, nel tuo caso, presumo che tu abbia già un Tester e modelli utente e tabelle dei tester e degli utenti.

Per aggiungere la chiave esterna è necessario creare una colonna intera con il nome user_id (convenzione):

add_column :tester, :user_id, :integer

Quindi aggiungere a appartiene_to al modello del tester:

class Tester < ActiveRecord::Base
  belongs_to :user
end

E potresti anche voler aggiungere un indice per la chiave esterna (questo è qualcosa che i riferimenti già fanno per te):

add_index :tester, :user_id

8

Quello farà il trucco:

rails g migration add_user_to_tester user_id:integer:index

Mi piace che questo aggiunga anche l'indice che molto probabilmente vorrai.
bheeshmar,

3

È possibile aggiungere riferimenti al modello tramite riga di comando nel modo seguente:

rails g migration add_column_to_tester user_id:integer

Questo genererà un file di migrazione come:

class AddColumnToTesters < ActiveRecord::Migration
  def change
    add_column :testers, :user_id, :integer
  end
end

Funziona bene ogni volta che lo uso ..


3

Per binari 4

Il generatore accetta il tipo di colonna come riferimenti (disponibile anche come belongs_to).

Questa migrazione creerà una user_idcolonna e un indice appropriato:

$ rails g migration AddUserRefToProducts user:references 

genera:

class AddUserRefToProducts < ActiveRecord::Migration
  def change
    add_reference :products, :user, index: true
  end
end

http://guides.rubyonrails.org/active_record_migrations.html#creating-a-standalone-migration

Per binari 3

Helper è chiamato riferimenti (disponibile anche come belongs_to).

Questa migrazione creerà una category_idcolonna del tipo appropriato. Si noti che si passa il nome del modello, non il nome della colonna. Active Record aggiunge ciò che fa _idper te.

change_table :products do |t|
  t.references :category
end

Se si dispone di belongs_toassociazioni polimorfiche, i riferimenti aggiungeranno entrambe le colonne richieste:

change_table :products do |t|
  t.references :attachment, :polymorphic => {:default => 'Photo'}
end

Aggiungerà una colonna attachment_id e una attachment_typecolonna stringa con un valore predefinito diPhoto .

http://guides.rubyonrails.org/v3.2.21/migrations.html#creating-a-standalone-migration

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.