Добавьте ссылочную миграцию столбцов в Rails 4

311

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

Вот что у меня есть. Я не уверен, должен ли я использовать (1) :user_id, :intили (2) :user, :references. Я даже не уверен, работает ли (2). Просто пытаюсь сделать это "рельсовым" способом.

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

Актуальный вопрос, кроме Rails 3. Миграции на Rails 3: Добавление ссылочного столбца?

Дон П
источник

Ответы:

708

Rails 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таблице), а также добавит индекс для нового столбца.

ОБНОВЛЕНИЕ [Для Rails 4.2]

Rails нельзя доверять для поддержания ссылочной целостности; Реляционные базы данных приходят нам на помощь здесь. Это означает, что мы можем добавить ограничения внешнего ключа на самом уровне базы данных и гарантировать, что база данных отклонит любую операцию, которая нарушает этот набор ссылочной целостности. Как прокомментировал @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: внешние ключи для вашей справки.

Кирти Торат
источник
8
Во многих случаях также полезно добавить внешний ключ. add_foreign_key (Rails 4.2)
poerror
18
Я полагаю, что вы можете сделать все в одной строке: add_reference: uploads,: user, index: true, foreign_key: true @KirtiThorat
user1801879
33
Теперь, если вы используете специальный синтаксис генератора для миграций, 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вместо строки add_foreign_key.
Вашингтон Ботелхо
2
Зачем нам и то foreign_keyи другое t.reference? По t.referenceсуществу не эквивалентно foriegn_key+ index?
геобой
190

Рельсы 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

Mirror318
источник
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
Сараванабалаги Рамачандран
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

[Использование Rails 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
vantony
источник
1
Этот ответ кажется дубликатом ответа @ Mirror318. Пожалуйста, прокомментируйте ответ выше, если вы думаете, что чего-то не хватает в нем. Спасибо.
М. Хабиб
8

Другой синтаксис того же действия:

rails g migration AddUserToUpload user:belongs_to
Надим Ясин
источник
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
Клинт Клинтон
источник