Rails 4'te bir referans sütun geçişi ekleme


310

Bir kullanıcının birçok yüklemesi var. Bir sütun eklemek istiyorumuploadsBaşvuru yapan tabloyauser . Göç nasıl olmalı?

İşte sahip olduğum şey. (1) :user_id, :intveya (2) kullanmam gerektiğinden emin değilim :user, :references. (2) 'nin çalışıp çalışmadığından bile emin değilim. Sadece bunu "raylar" yolu yapmaya çalışıyorum.

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

Rails 3 hariç ilgili soru. Rails 3 geçişleri: Referans sütun eklensin mi?

Yanıtlar:


706

Raylar 4.x

Ne zaman zaten users ve uploadstabloları ve isteyen yeni bir ilişki eklemek aralarında.

Tek yapmanız gereken aşağıdaki komutu kullanarak bir taşıma oluşturmaktır:

rails g migration AddUserToUploads user:references

Bir taşıma dosyası şu şekilde oluşturulur:

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

Ardından, taşıma işlemini kullanarak çalıştırın rake db:migrate. Bu göç adlı yeni sütun ekleyerek ilgilenir user_idiçin uploadstablodaki (referans idsütunu userstabloya), ARTI aynı zamanda yeni bir sütun üzerinde dizin ekleyecektir.

GÜNCELLEME [Rails 4.2 için]

Referans bütünlüğünü korumak için raylara güvenilemez; ilişkisel veritabanları kurtarmaya geliyor. Bunun anlamı, veritabanı düzeyinde yabancı anahtar kısıtlamaları ekleyebilmemiz ve veritabanının bu küme referans bütünlüğünü ihlal eden herhangi bir işlemi reddetmesini sağlayabilmemizdir. @ İnfofo'nun yorumladığı gibi, Rails 4.2 yabancı anahtarlar için yerel destekle birlikte gelir (referans bütünlüğü) . Gerekli değildir, ancak yukarıda oluşturduğumuz referansa yabancı anahtar (çok yararlı olduğu için) eklemek isteyebilirsiniz.

Varolan bir referansa yabancı anahtar eklemek için , yabancı bir anahtar eklemek için yeni bir göç oluşturun:

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

Yabancı anahtarla tamamen yeni bir referans oluşturmak için (Rails 4.2'de) , aşağıdaki komutu kullanarak bir taşıma oluşturun:

rails g migration AddUserToUploads user:references

bir taşıma dosyası şu şekilde oluşturulur:

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

Bu user_id, uploadstablonun sütununa yeni bir yabancı anahtar ekleyecektir . Anahtaridusers tablodaki sütuna başvurur.

NOT: Bu, bir başvuru eklemeye ek olarak, ilk önce yabancı anahtardan sonra bir referans oluşturmanız gerekir ( aynı geçişte veya ayrı bir geçiş dosyasında bir yabancı anahtar oluşturmayı seçebilirsiniz ). Active kayıt sadece tek sütun yabancı anahtarlarını destekler ve şu anda sadece mysql, mysql2ve PostgreSQLadaptörleri desteklenmektedir. Bunu sqlite3, vb. Gibi diğer adaptörlerle denemeyin . Referans için Ray Kılavuzları: Yabancı Anahtarlar'a bakın.


8
Birçok durumda yabancı anahtar eklemek de iyidir. add_foreign_key (Rails 4.2)
15'te Poerror

18
Hepsini bir satırda yapabileceğinize inanıyorum: add_reference: yüklemeler,: kullanıcı, dizin: true, foreign_key: true @KirtiThorat
user1801879 7:15

32
Şimdi, taşıma işlemleri için özel jeneratör sözdizimini kullanırsanız, Rails 4.2 otomatik olarak dahil edilen yabancı anahtar kısıtlamalarıyla doğru taşıma işlemini oluşturur. uygun göçte rails g migration AddUserToUploads user:referencesüretir add_reference :uploads, :user, index: true, foreign_key: true.
jrhorn424

10
...index: true, foreign_key: trueBunun yerine o satırını kullanın add_foreign_key.
Washington Botelho

2
Neden ikisine de ihtiyacımız var foreign_keyve t.reference? t.referenceEsasen foriegn_key+ ile eşdeğer değil indexmi?
geoboy

188

Raylar 5

Taşıma işlemini oluşturmak için bu komutu kullanmaya devam edebilirsiniz:

rails g migration AddUserToUploads user:references

Taşıma öncekinden biraz farklı görünüyor, ancak yine de çalışıyor:

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

Unutmayın :user, değil:user_id


2
Ad aralıklı sınıflar için, Local::Userbunun Usergibi bir şey yapmak gibi rails g migration AddLocalUserToUploads user:references.
Ka Mok

3
bunu otomatik olarak ekliyor mu:index
Saravanabalagi Ramachandran

4
@Zeke Evet, taşıma işlemini çalıştırın ve şemanızı kontrol edin, şöyle bir şey söylemelidirt.index ["user_id"], name: "index_uploads_on_user_id", using: :btree
Mirror318

1
Evet, manuel olarak taşıma add_index eklediğimde "dizin var" hatası aldım: P @ Mirror318
Saravanabalagi Ramachandran

2
Ayrıca eklemek gerekir belongs_to :userde Uploadbiz kullanabilmesi için, sınıfın upload.userkullanıcı örneğini alır.
Wit

17

upve downyöntemiyle başka bir alternatif yaklaşımdan hoşlanıyorsanız şunu deneyin:

  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

9

[Rails 5 Kullanılması]

Taşıma oluşturun:

rails generate migration add_user_reference_to_uploads user:references

Bu taşıma dosyasını oluşturur:

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

Şimdi şema dosyasını gözlemlerseniz, karşıya yükleme tablosunun yeni bir alan içerdiğini göreceksiniz. Gibi bir şey: t.bigint "user_id"veya t.integer "user_id".

Veritabanını taşı:

rails db:migrate

1
Bu cevap @ Mirror318'in cevabının kopyası gibi görünüyor. Bir şey eksik olduğunu düşünüyorsanız lütfen yukarıdaki cevaba yorum yapın. Teşekkürler.
M. Habib

8

Aynı şeyi yapmanın başka bir sözdizimi:

rails g migration AddUserToUpload user:belongs_to

7

Birisinin aynı sorunu olup olmadığını belgelemek için ...

Benim durumumda :uuidalanları kullanıyorum ve yukarıdaki yanıtlar benim durumumda çalışmıyor, çünkü raylar 5 :bigintbunun yerine bir sütun oluşturuyor :uuid:

add_column :uploads, :user_id, :uuid
add_index :uploads, :user_id
add_foreign_key :uploads, :users

Ayrıca neler olduğu çok daha net. Ama evet UUID artık standart olmalı.
hadees

2

Bir taşıma dosyası oluşturma

rails generate migration add_references_to_uploads user:references

Varsayılan yabancı anahtar adı

Bu, yüklemeler tablosunda yabancı anahtar olarak bir user_id sütunu oluşturur

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

kullanıcı modeli:

class User < ApplicationRecord
  has_many :uploads
end

model yükle:

class Upload < ApplicationRecord
  belongs_to :user
end

Yabancı anahtar adını özelleştirin:

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

Bu, yükleme tablolarında yabancı anahtar olarak bir yazar_kimliği sütunu oluşturur.

kullanıcı modeli:

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

model yükle:

class Upload < ApplicationRecord
  belongs_to :user
end
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.