Migracje Rails 3: Dodajesz kolumnę referencyjną?


162

Jeśli utworzę nową migrację rails 3 z (na przykład)

rails g migration tester title:tester user:references

wszystko działa dobrze ... jeśli jednak dodam kolumnę z czymś w rodzaju:

rails g migration add_user_to_tester user:references

pole odniesienia nie jest rozpoznawane. Krótko mówiąc, pytanie brzmi: jak dodać kolumnę odwołującą się do migracji szyn z wiersza poleceń?

Odpowiedzi:


205

Jeśli korzystasz z Rails 4.x , możesz teraz generować migracje z referencjami, takimi jak:

rails generate migration AddUserRefToProducts user:references

jak widać na prowadnicach szyn



2
jak określić nazwę kolumny dla klucza obcego zamiast automatycznie wygenerowanej nazwy?
j będzie

@jwill możesz użyć polymorphic: user: referencje {polymorphic}.
Paulo Fidalgo,

@PauloFidalgo Czy możesz trochę wyjaśnić, jak to zrobić? może jakiś przewodnik po linkach? (mowa o polimorfii)
Anwar


186

EDYCJA : To jest nieaktualna odpowiedź i nie należy się o nią ubiegać Rails 4.x +

Nie musisz dodawać odwołań, jeśli możesz użyć identyfikatora całkowitego do klasy, do której się odwołujesz.

Powiedziałbym, że zaletą używania referencji zamiast zwykłej liczby całkowitej jest to, że model zostanie wstępnie zdefiniowany z przypisaniem do niego, a ponieważ model jest już utworzony i nie będzie to miało wpływu na migrację czegoś istniejącego, cel jest trochę stracony.

Więc zamiast tego zrobiłbym to:

rails g migration add_user_id_to_tester user_id:integer

A następnie ręcznie dodaj should_to: user w modelu Tester


9
Ale to nie stworzy odpowiednich ograniczeń klucza obcego w bazach danych, które go obsługują, prawda?
abahgat

19
Nie, afaik Railsy nigdy nie tworzą ograniczeń klucza obcego w bazie danych, chyba że dodasz wtyczki, które zrobią to za Ciebie.
DanneManne

właśnie studiując ten post, pls Jak dodać odniesienie po wszystkim
El nino

13
pamiętaj, aby dodać indeks z użytkownikiem: integer: index
rickypai

3
Odpowiedź jest datowana, zobacz odpowiedź @ Paulo na temat nowoczesnych szyn.
OneHoopyFrood

102

Zwróć uwagę, że najprawdopodobniej będziesz potrzebować indeksu również w tej kolumnie.

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

1
Czemu? Czy jest to prawdą w przypadku większości relacji should_to?
ahnbizcad

Jest to rzeczywiście ze względu na wydajność i przydaje się, jeśli masz has_many / has_one po drugiej stronie relacji bring_to. Jeśli jesteś absolutnie pewien, że nie przejdziesz user.testers, możesz pominąć indeks.
Eugene

1
rails g migration ...Generowane add_reference :installs, :device, index: truektóry również tworzy indeks.
B Seven

49

W przypadku dwóch poprzednich kroków opisanych powyżej nadal brakuje ograniczenia klucza obcego. To powinno działać:

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

To jedyna rzeczywista odpowiedź. Klucz obcy jest tutaj najbardziej krytyczną częścią
user2490003

to powinno być zaznaczone jako poprawna odpowiedź, ponieważ pytania dotyczą torów 3
Carlos Roque

35

Państwo może używać odwołań w migracji zmian. To jest prawidłowy kod Rails 3.2.13:

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
metody zmiany i wyłączenia? czy nie są zamiast tego metody w górę iw dół?
MaicolBen

@MaicolBen tak, możesz też po prostu zrezygnować z metody down.
Hut8

@MaicolBen Bez downmetody otrzymałem ActiveRecord::IrreversibleMigrationpodczas wycofywania się przy użyciu Railsów 3.2. Miałem również do zmian changena up.
Andrew Grimm

27

Uruchomienie rails g migration AddUserRefToSponsors user:referenceswygeneruje następującą migrację:

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

Do której wersji Railsów to służy?
Andrew Grimm

8

Dodając kolumnę, musisz uczynić tę kolumnę liczbą całkowitą i, jeśli to możliwe, trzymać się konwencji rails. Więc dla twojego przypadku zakładam, że masz już modele Tester i User oraz tabele testerów i użytkowników.

Aby dodać klucz obcy, musisz utworzyć kolumnę z liczbą całkowitą o nazwie user_id (konwencja):

add_column :tester, :user_id, :integer

Następnie dodaj należeć do modelu testera:

class Tester < ActiveRecord::Base
  belongs_to :user
end

Możesz także dodać indeks dla klucza obcego (jest to coś, co już robią referencje):

add_index :tester, :user_id

8

To wystarczy:

rails g migration add_user_to_tester user_id:integer:index

Podoba mi się, że to również dodaje indeks, który najprawdopodobniej będzie Ci potrzebny.
bheeshmar

3

Możesz dodać odniesienia do swojego modelu za pomocą wiersza poleceń w następujący sposób:

rails g migration add_column_to_tester user_id:integer

Spowoduje to wygenerowanie pliku migracji, takiego jak:

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

Działa to dobrze za każdym razem, gdy go używam.


3

Do szyn 4

Generator przyjmuje typ kolumny jako referencje (dostępny również jako belongs_to).

Ta migracja utworzy user_idkolumnę i odpowiedni indeks:

$ rails g migration AddUserRefToProducts user:references 

generuje:

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

Do szyn 3

Pomocnik jest nazywany referencjami (dostępny również jako belongs_to).

Ta migracja spowoduje utworzenie category_idkolumny odpowiedniego typu. Zwróć uwagę, że przekazujesz nazwę modelu, a nie nazwę kolumny. Moduł Active Record dodaje _iddla Ciebie.

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

Jeśli masz belongs_toasocjacje polimorficzne, odwołania dodają obie wymagane kolumny:

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

Dodaje kolumnę załącznika_id i attachment_typekolumnę z ciągiem znaków o domyślnej wartości Photo.

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

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.