Додайте міграцію еталонних стовпців у Rails 4


310

Користувач має багато завантажень. Я хочу додати стовпчик до uploadsтаблиці, на який посилається user. Як повинна виглядати міграція?

Ось що я маю. Я не впевнений, чи варто використовувати (1) :user_id, :intабо (2) :user, :references. Я навіть не впевнений, чи працює (2). Просто намагаюся зробити це «рейки» способом.

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

Відповідне питання, окрім рейок 3. Міграція рейок 3: Додавання стовпчика-опорного стовпчика?

Відповіді:


706

Рейки 4.x

Коли ви вже users і uploadsтаблиці і хочете додати нові відносини між ними.

Все, що вам потрібно зробити: просто створити міграцію за допомогою наступної команди:

rails g migration AddUserToUploads user:references

Який створить файл міграції як:

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

Потім запустіть міграцію за допомогою rake db:migrate. Ця міграція допоможе додати новий стовпець, названий user_idдо uploadsтаблиці (посилаючись на idстовпець у usersтаблиці), PLUS також додасть індекс у новому стовпчику.

ОНОВЛЕННЯ [Для рейок 4.2]

Рейки не можна довіряти, щоб підтримувати референтну цілісність; Тут нам допомагають реляційні бази даних . Це означає, що ми можемо додавати обмеження для зовнішніх ключів на самому рівні бази даних і гарантувати, що база даних буде відхиляти будь-яку операцію, що порушує цю задану цілісність. Як прокоментував @infoget, Rails 4.2 поставляється з вбудованою підтримкою зовнішніх ключів (референтна цілісність) . Це не потрібно, але ви можете додати іноземний ключ (як це дуже корисно) до посилання, яке ми створили вище.

Щоб додати іноземний ключ до існуючої посилання , створіть нову міграцію, щоб додати зовнішній ключ:

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

Щоб створити абсолютно нову посилання з іноземним ключем (в Rails 4.2) , створіть міграцію, використовуючи таку команду:

rails g migration AddUserToUploads user:references

який створить файл міграції як:

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

Це додасть новий зовнішній ключ до user_idстовпця uploadsтаблиці. Ключ посилається на idстовпчик у usersтаблиці.

ПРИМІТКА. Це додатково до додавання посилання, тому вам все одно потрібно створити посилання спочатку, а потім закордонний ключ ( ви можете створити іноземний ключ у тій же міграції або окремому файлі міграції ). Active Record підтримує лише зовнішні клавіші для одного стовпця та в даний час mysql, mysql2і PostgreSQLадаптери підтримуються. Не намагайтеся цього використовувати з іншими адаптерами, наприклад sqlite3тощо. Для отримання довідки зверніться до Rails Guides: Foreign Keys .


8
У багатьох випадках добре також додати іноземний ключ. add_foreign_key (Rails 4.2)
poerror

18
Я вважаю, що ви можете зробити все в одному рядку: add_reference: uploads,: user, index: true, Foreign_key: true @KirtiThorat
user1801879

32
Тепер, якщо ви використовуєте спеціальний синтаксис генератора для міграцій, Rails 4.2 автоматично створить правильну міграцію із включеними обмеженнями зовнішніх ключів. rails g migration AddUserToUploads user:referencesвиробляє add_reference :uploads, :user, index: true, foreign_key: trueу відповідній міграції.
jrhorn424

10
Використовуйте ...index: true, foreign_key: trueзамість o лінію add_foreign_key.
Вашингтон Ботелхо

2
Навіщо нам потрібно і те, foreign_keyі t.reference? По t.referenceсуті не є еквівалентом foriegn_key+ index?
геобой

187

Рейки 5

Ви можете використовувати цю команду для створення міграції:

rails g migration AddUserToUploads user:references

Міграція виглядає дещо інакше, ніж раніше, але все ще працює:

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

Зауважте, що це :userне так:user_id


2
Для класів з іменами, наприклад, Local::Userзамість того, щоб Userробити щось подібне rails g migration AddLocalUserToUploads user:references.
Ка Мок

3
це автоматично додає:index
Сараванабалагі Рамачандран

4
@Zeke Так, запустіть міграцію та перевірте свою схему, вона повинна сказати щось на кшталтt.index ["user_id"], name: "index_uploads_on_user_id", using: :btree
Mirror318

1
так, я отримав помилку "існує індекс", коли я вручну додав add_index під час міграції: P @ Mirror318
Saravanabalagi Ramachandran

2
Нам також слід додати belongs_to :userв Uploadкласі, щоб ми могли використовувати upload.userдля отримання екземпляра користувача.
Віт

17

якщо ви хочете ще один альтернативний підхід з upі downспосіб спробувати це:

  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

[Використання рейок 5]

Створити міграцію:

rails generate migration add_user_reference_to_uploads user:references

Це створить файл міграції:

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

Тепер, якщо ви спостерігаєте файл схеми, ви побачите, що таблиця завантажень містить нове поле. Щось на кшталт: t.bigint "user_id"або t.integer "user_id".

Перемістити базу даних:

rails db:migrate

1
Ця відповідь здається дублюючою відповіді @ Mirror318. Будь ласка, прокоментуйте вищезгадану відповідь, якщо ви думаєте, що щось відсутнє. Дякую.
М. Хабіб


7

Просто документуйте, якщо хтось має таку ж проблему ...

У моїй ситуації я використовував :uuidполя, і вищевказані відповіді не працюють у моєму випадку, оскільки рейки 5 створюють стовпчик, використовуючи :bigintнатомість :uuid:

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

Також набагато зрозуміліше, що відбувається. Але так, UUID має бути стандартним зараз.
хадеси

2

Створіть файл міграції

rails generate migration add_references_to_uploads user:references

Ім'я іноземного ключа за замовчуванням

Це створило б стовпець user_id у таблиці завантажень як зовнішній ключ

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

модель користувача:

class User < ApplicationRecord
  has_many :uploads
end

модель завантаження:

class Upload < ApplicationRecord
  belongs_to :user
end

Налаштувати ім'я іноземного ключа:

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

Це створило б стовпець author_id у таблицях завантажень як зовнішній ключ.

модель користувача:

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

модель завантаження:

class Upload < ApplicationRecord
  belongs_to :user
end
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.