Dodaj migrację kolumny referencyjnej w Railsach 4

310

Użytkownik ma wiele przesłanych plików. Chcę dodać kolumnę do uploadstabeli, która odwołuje się do user. Jak powinna wyglądać migracja?

Oto co mam. Nie jestem pewien, czy powinienem użyć (1) :user_id, :intczy (2) :user, :references. Nie jestem nawet pewien, czy (2) działa. Próbuję to zrobić po prostu „szynami”.

class AddUserToUploads < ActiveRecord::Migration
  def change
    add_column :uploads, :user_id, :integer
  end
end

Odpowiednie pytanie oprócz Rails 3. Migracje Rails 3: Czy dodać kolumnę referencyjną?

Don P.
źródło

Odpowiedzi:

706

Szyny 4.x

Gdy już masz users i uploadstabele i chcą dodać nową relację między nimi.

Wszystko, co musisz zrobić, to: po prostu wygenerować migrację za pomocą następującego polecenia:

rails g migration AddUserToUploads user:references

Który utworzy plik migracji jako:

class AddUserToUploads < ActiveRecord::Migration
  def change
    add_reference :uploads, :user, index: true
  end
end

Następnie uruchom migrację za pomocą rake db:migrate. Ta migracja zajmie się dodaniem nowej kolumny o nazwie user_iddo uploadstabeli (odwołując się do idkolumny w userstabeli), a także doda indeks do nowej kolumny.

AKTUALIZACJA [For Rails 4.2]

Nie można ufać Railsom, aby zachowały integralność referencyjną; Relacyjne bazy danych przychodzą nam z pomocą. Oznacza to, że możemy dodawać ograniczenia klucza obcego na poziomie samej bazy danych i upewnić się, że baza danych odrzuci każdą operację, która narusza integralność referencyjną tego zestawu. Jak skomentował @infoget, Rails 4.2 jest dostarczany z natywną obsługą kluczy obcych (integralność referencyjna) . Nie jest to wymagane, ale możesz dodać klucz obcy (ponieważ jest to bardzo przydatne) do odwołania, które utworzyliśmy powyżej.

Aby dodać klucz obcy do istniejącego odwołania , utwórz nową migrację, aby dodać klucz obcy:

class AddForeignKeyToUploads < ActiveRecord::Migration
  def change
    add_foreign_key :uploads, :users
  end
end

Aby utworzyć całkowicie nowe odniesienie z kluczem obcym (w Rails 4.2) , wygeneruj migrację za pomocą następującego polecenia:

rails g migration AddUserToUploads user:references

który utworzy plik migracji jako:

class AddUserToUploads < ActiveRecord::Migration
  def change
    add_reference :uploads, :user, index: true
    add_foreign_key :uploads, :users
  end
end

Spowoduje to dodanie nowego klucza obcego do user_idkolumny uploadstabeli. Klucz odwołuje się do idkolumny w userstabeli.

UWAGA: Jest to dodatek do dodawania odwołania, więc nadal musisz najpierw utworzyć odniesienie, a następnie klucz obcy ( możesz wybrać utworzenie klucza obcego w tej samej migracji lub osobnym pliku migracji ). Active Record obsługuje tylko klucze obce jednokolumnowe i obecnie tylko mysql, mysql2a PostgreSQLkarty są obsługiwane. Nie próbuj tego z innymi adapterami, takimi jak sqlite3, itp. Zapoznaj się z Przewodnikami po szynach: Klucze obce w celach informacyjnych.

Kirti Thorat
źródło
8
W wielu przypadkach dobrze jest również dodać klucz obcy. add_foreign_key (Rails 4.2)
poerror
18
Wierzę, że możesz zrobić wszystko w jednym wierszu: add_reference: uploads,: user, index: true, Foreign_key: true @KirtiThorat
user1801879
32
Teraz, jeśli użyjesz specjalnej składni generatora do migracji, Railsy 4.2 automatycznie utworzą poprawną migrację z uwzględnieniem ograniczeń klucza obcego. rails g migration AddUserToUploads user:referencespowoduje add_reference :uploads, :user, index: true, foreign_key: trueodpowiednią migrację.
jrhorn424
10
Użyj ...index: true, foreign_key: truezamiast o linii add_foreign_key.
Washington Botelho,
2
Dlaczego potrzebujemy zarówno foreign_keyi t.reference? Czy t.referencezasadniczo nie jest równoważne z foriegn_key+ index?
geoboy
187

Szyny 5

Nadal możesz użyć tego polecenia, aby utworzyć migrację:

rails g migration AddUserToUploads user:references

Migracja wygląda nieco inaczej niż wcześniej, ale nadal działa:

class AddUserToUploads < ActiveRecord::Migration[5.0]
  def change
    add_reference :uploads, :user, foreign_key: true
  end
end

Zauważ, że :usernie:user_id

Mirror318
źródło
2
W przypadku klas z odstępami między nazwami, Local::Userzamiast Userrobić coś podobnego rails g migration AddLocalUserToUploads user:references.
Ka Mok
3
dodaje to automatycznie:index
Saravanabalagi Ramachandran
4
@Zeke Tak, uruchom migrację i sprawdź swój schemat, powinien on powiedzieć coś w stylut.index ["user_id"], name: "index_uploads_on_user_id", using: :btree
Mirror318
1
tak, dostałem błąd „indeks istnieje”, gdy ręcznie dodałem add_index w migracji: P @ Mirror318
Saravanabalagi Ramachandran
2
Trzeba też dodać belongs_to :userw Uploadklasie, więc możemy użyć upload.user, aby uzyskać instancję użytkownika.
Wit
17

jeśli podoba Ci się inne alternatywne podejście upi downmetoda, spróbuj tego:

  def up
    change_table :uploads do |t|
      t.references :user, index: true
    end
  end

  def down
    change_table :uploads do |t|
      t.remove_references :user, index: true
    end
  end
Kiry Meas
źródło
9

[Korzystanie z Rails 5]

Generuj migrację:

rails generate migration add_user_reference_to_uploads user:references

Spowoduje to utworzenie pliku migracji:

class AddUserReferenceToUploads < ActiveRecord::Migration[5.1]
  def change
    add_reference :uploads, :user, foreign_key: true
  end
end

Teraz, jeśli zaobserwujesz plik schematu, zobaczysz, że tabela przesyłania zawiera nowe pole. Coś w stylu: t.bigint "user_id"lub t.integer "user_id".

Przeprowadź migrację bazy danych:

rails db:migrate
vantony
źródło
1
Ta odpowiedź wydaje się być duplikatem odpowiedzi @ Mirror318. Proszę skomentować powyższą odpowiedź, jeśli uważasz, że czegoś brakuje. Dzięki.
M. Habib,
8

Inną składnią robienia tego samego jest:

rails g migration AddUserToUpload user:belongs_to
Nadeem Yasin
źródło
7

Aby udokumentować, czy ktoś ma ten sam problem ...

W mojej sytuacji używam :uuidpól, a powyższe odpowiedzi nie działają w moim przypadku, ponieważ szyny 5 tworzą kolumnę, używając :bigintzamiast tego :uuid:

add_column :uploads, :user_id, :uuid
add_index :uploads, :user_id
add_foreign_key :uploads, :users
Bruno Casali
źródło
Jest również o wiele jaśniejsze, co się dzieje. Ale tak, UUID powinien być teraz standardem.
hadees
2

Utwórz plik migracji

rails generate migration add_references_to_uploads user:references

Domyślna nazwa klucza obcego

Spowoduje to utworzenie kolumny user_id w tabeli przesyłania jako klucza obcego

class AddReferencesToUploads < ActiveRecord::Migration[5.2]
  def change
    add_reference :uploads, :user, foreign_key: true
  end
end

model użytkownika:

class User < ApplicationRecord
  has_many :uploads
end

prześlij model:

class Upload < ApplicationRecord
  belongs_to :user
end

Dostosuj nazwę klucza obcego:

add_reference :uploads, :author, references: :user, foreign_key: true

Spowoduje to utworzenie kolumny autor_id w tabelach przesyłania jako klucza obcego.

model użytkownika:

class User < ApplicationRecord
  has_many :uploads, foreign_key: 'author_id'
end

prześlij model:

class Upload < ApplicationRecord
  belongs_to :user
end
Clint Clinton
źródło