Указание имени столбца в переносе «ссылок»


124

Я хочу создать migrationв Rails ссылку на другую таблицу. Обычно я делал что-то вроде:

add_column :post, :user, :references

Это создает столбец с именем user_idв postsтаблице. Но что, если вместо этого user_idя хочу что-то вроде author_id? Как я могу это сделать?

Ответы:


59

Сделайте это вручную:

add_column :post, :author_id, :integer

но теперь, когда вы создаете оператор own_to, вам придется его изменить, поэтому теперь вам нужно вызвать

def post
    belongs_to :user, :foreign_key => 'author_id'
end

1
Разве мне не нужно добавлять индекс?
caarlos0 04

1
Да, вам нужно будет создать индекс при миграции.
Том Харрисон

1
Rails читы - по умолчанию он не использует индексы. Теперь, если вам нужны индексы (что является отличной идеей - несмотря на то, что рельсы полностью игнорируют их), вы, безусловно, можете их добавить. Вы захотите ознакомиться с руководством, на которое я ссылаюсь, для получения дополнительной информации о миграции в целом, и вы даже можете в конечном итоге поместить вызывающий код SQL непосредственно в свою миграцию. Я бы сказал, игнорируйте это, так как это не обычная часть рельсов, вы получите от него 0 производительность, поскольку сгенерированные по умолчанию SQL-запросы рельсов не используют его. ссылка
mschultz 04

хм понял. Большое спасибо!
caarlos0 04

используя schema_plusgem, t.references :category, index: true, foreign_key: true, references: :match_categoriesтакже работал у меня в файле миграции.
elquimista

251

Для Rails 5+

Исходное определение:

Если вы определяете вашу Postмодель таблицы, вы можете установить references, indexи foreign_keyв одной строке:

t.references :author, index: true, foreign_key: { to_table: :users }

Существующее обновление:

Если вы добавляете ссылки в существующую таблицу, вы можете сделать это:

add_reference :posts, :author, foreign_key: { to_table: :users }

Примечание. Значение по умолчанию для indextrue.


Допускает ли исходное определение нули? Если нет, знаете ли вы альтернативу, допускающую значение NULL?
Vorpulus Lyphane

5
Это определение позволяет nulls. Чтобы не допустить их, добавьте обычный вариант null: false.
Ашитака

Спасибо. Для «Первоначального определения» я думаю, что «index: true» не нужен. Я получаю такое же изменение схемы с ним или без него. Неважно; только что увидел твою записку в конце.
Joey

Спасибо, это то, что я искал!
Филипп Б.

250

В Rails 4.2+ вы также можете установить внешние ключи в db, что является отличной идеей .

Для простых ассоциаций это можно сделать и при t.referencesдобавлении foreign_key: true, но в этом случае вам понадобятся две строки.

# The migration
add_reference :posts, :author, index: true
add_foreign_key :posts, :users, column: :author_id

# The model
belongs_to :author, class_name: "User"

2
Спасибо, но вопрос помечен как Rails3, я рад просто помочь
ecoologic

2
Ох, я этого не заметил. Что ж, мне это очень помогло. :)
bonh

2
Я почти потерял надежду, когда увидел это! Спасибо @ecoologic!
Дэн Уильямс

2
@ecoologic, вы можете добавить только одну вещь: add_foreign_key - это только рельсы 4.2+. ;)
Дэн Уильямс

4
Я не уверен, что вам нужна references: :usersопция add_referenceзвонка. Я не вижу, чтобы это было задокументировано в документации, и, похоже, с моей стороны он работает без этого.
jakecraige

87

В rails 4 при использовании postgresql и гема schema_plus вы можете просто написать

add_reference :posts, :author, references: :users

Это создаст столбец author_id, который правильно относится к users(id).

И в своей модели вы пишете

belongs_to :author, class_name: "User"

Обратите внимание, что при создании новой таблицы вы можете записать ее следующим образом:

create_table :things do |t| 
  t.belongs_to :author, references: :users 
end 

Примечание: schema_plusгем в целом несовместим с rails 5+, но эта функциональность предлагается гем schema_auto_foreign_keys (часть schema_plus), который совместим с rails 5.


28
и если вы используете create_table:t.references :author, references: :users
Михаил Радионов

2
Добавление комментария @ MichaelRadionov к вашему ответу сделает его идеальным.
toxaq

2
Я просматривал исходный код Rails 4.1 и не могу найти никаких доказательств, которые :referencesдействительно что-то делают.
jes5199 08

1
Да, вы правы, я использую этот schema_plusдрагоценный камень целую вечность, и он фактически добавляет эту функциональность. Я соответствующим образом отредактировал свой ответ.
nathanvda

2
В Rails 6 кажется, что синтаксис t.references :col_name, references: other_table_nameработает без установки дополнительных гемов.
Qqwy

51

Если вы не используете внешний ключ, то не имеет значения, каково фактическое имя другой таблицы.

add_reference :posts, :author

Начиная с Rails 5 , если вы используете внешний ключ, вы можете указать имя другой таблицы в параметрах внешнего ключа. (см. https://github.com/rails/rails/issues/21563 для обсуждения)

add_reference :posts, :author, foreign_key: {to_table: :users}

До Rails 5 вы должны добавить внешний ключ как отдельный шаг:

add_foreign_key :posts, :users, column: :author_id

12
to_table - форма множественного числа:{to_table: :users}
hoffmanc

-3

alias_attribute (new_name, old_name) очень удобен. Просто создайте свою модель и отношения:

rails g model Post title user:references

затем отредактируйте модель и добавьте псевдоним атрибута с

alias_attribute :author, :user

После этого вы сможете запускать такие вещи, как

Post.new(title: 'My beautiful story', author: User.first)

1
это не работает, когда вам нужно определить несколько ссылок на другую модель, например, сообщение (автор, редактор)
ultrajohn
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.