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

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

add_column :post, :user, :references

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


person caarlos0    schedule 04.12.2012    source источник


Ответы (6)


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

add_column :post, :author_id, :integer

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

def post
    belongs_to :user, :foreign_key => 'author_id'
end
person mschultz    schedule 04.12.2012
comment
Разве мне не нужно добавлять какой-либо индекс? - person caarlos0; 04.12.2012
comment
Да, вам нужно будет создать индекс при миграции. - person Tom Harrison; 04.12.2012
comment
Читы Rails - по умолчанию он не использует индексы. Теперь, если вам нужны индексы (что является отличной идеей, несмотря на то, что рельсы будут полностью их игнорировать), вы, безусловно, можете их добавить. Вы захотите ознакомиться с руководством, на которое я ссылаюсь, для получения дополнительной информации о миграции в целом, и вы даже можете в конечном итоге включить код вызова SQL непосредственно в свою миграцию. Я бы сказал, игнорируйте это, так как это не нормальная часть рельсов, вы получите от этого 0 производительности, поскольку SQL-запросы, сгенерированные по умолчанию, не используют это преимущество. ссылка - person mschultz; 04.12.2012
comment
хм понял. Большое спасибо! - person caarlos0; 04.12.2012
comment
используя schema_plus gem, t.references :category, index: true, foreign_key: true, references: :match_categories также работал у меня в файле миграции. - person elquimista; 28.02.2016
comment
Я бы предложил использовать bigint вместо integer, так как это тип столбца по умолчанию для первичных ключей для Rails 5.1+. - person Giovanni Benussi; 11.12.2018
comment
На данный момент, вероятно, стоит отметить, что ВСЕ это устарело, особенно со времен Rails5, в котором есть лучшие способы сделать это. - person mschultz; 23.10.2019

Для рельсов 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 }

Примечание. Значением по умолчанию для index является true.

person Sheharyar    schedule 05.02.2017
comment
Будет ли исходное определение допускать нули? Если нет, знаете ли вы обнуляемую альтернативу? - person Vorpulus Lyphane; 19.05.2017
comment
Это определение позволяет nulls. Чтобы их не допустить, добавьте обычную опцию null: false. - person Ashitaka; 27.11.2017
comment
Спасибо. Для начального определения я думаю, что index: true не нужен. Я получаю одно и то же изменение схемы с ним или без него. Не бери в голову; только что увидел вашу заметку в конце. - person Joey; 15.12.2017
comment
Спасибо, это то, что я искал! - person Philippe B.; 05.10.2018

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

Для простых ассоциаций это можно сделать и на 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"
person ecoologic    schedule 11.04.2015
comment
Спасибо, но вопрос помечен как Rails3, буду рад помочь - person ecoologic; 18.02.2016
comment
Ой, я этого не заметил. Что ж, это было очень полезно для меня. :) - person bonh; 18.02.2016
comment
Рад слышать (; - person ecoologic; 18.02.2016
comment
Я почти потерял надежду, когда увидел это! Спасибо @ecoologic! - person Dan Williams; 13.05.2016
comment
@ecoologic, вы можете добавить только одну вещь: add_foreign_key — это только рельсы 4.2+. ;) - person Dan Williams; 13.05.2016
comment
Есть ли соответствующий синтаксис для has_many? - person Jeffrey Basurto; 05.06.2016
comment
@JeffreyBasurto столбец всегда идет в belong_to части отношения, надеюсь, это ответит на ваш вопрос - person ecoologic; 05.06.2016
comment
Я не уверен, что вам нужна опция references: :users в вызове add_reference. Я не вижу, чтобы это было задокументировано в документах, и, похоже, оно работает с моей стороны без него. - person jakecraige; 01.03.2017
comment
Глядя на источник, он действительно ничего не делает с необязательным аргументом references. И я думаю, что способ его настройки не имеет значения, если нет таблицы с именем authors, все, что он делает, это добавляет столбец с именем author_id. Однако имеет значение, если вы хотите создать ограничение внешнего ключа, потому что тогда оно пытается использовать его в качестве имени таблицы, поэтому, если вы хотите это сделать, вам нужно будет иметь отдельный оператор add_foreign_key. - person Ibrahim; 06.02.2018
comment
Привет, ребята, спасибо за исправление, я обновляю это прямо сейчас. Я не могу вспомнить, откуда я это взял (прошло несколько лет). Спасибо. - person ecoologic; 06.02.2018

В 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.

person nathanvda    schedule 13.03.2014
comment
и если вы используете create_table: t.references :author, references: :users - person Michael Radionov; 06.04.2014
comment
Добавление комментария @MichaelRadionov к вашему ответу сделает его идеальным. - person toxaq; 12.04.2015
comment
Я просматривал исходный код Rails 4.1 и не нашел доказательств того, что :references действительно что-то делает. - person jes5199; 08.11.2015
comment
Да, вы правы, я использую гем schema_plus целую вечность, и на самом деле он добавляет эту функциональность. Я отредактировал свой ответ соответственно. - person nathanvda; 27.01.2016
comment
В Rails 6 кажется, что синтаксис t.references :col_name, references: other_table_name работает без установки дополнительных гемов. - person Qqwy; 09.09.2019

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

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
person jes5199    schedule 08.11.2015
comment
Обратите внимание, что rails g migration AddAuthorToPosts author:references не может вывести это. Вы должны вручную обновить миграцию (см.: github.com/rails/rails/blob/main/railties/lib/rails/generators/) - person Christopher Oezbek; 26.02.2021

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)
person sekmo    schedule 30.03.2017
comment
это не работает, когда вам нужно определить несколько ссылок на другую модель, например, сообщение (автор, редактор) - person ultrajohn; 07.04.2017