Вказівка ​​імені стовпця при переміщенні "посилань"


124

Я хочу зробити migrationв Rails, посилаючись на іншу таблицю. Зазвичай я б робив щось на кшталт:

add_column :post, :user, :references

Це створює стовпчик, названий user_idу postsтабл. Але що робити, якщо замість цього user_idя хочу щось подібне author_id? Як я можу це зробити?

Відповіді:


59

Зробіть це вручну:

add_column :post, :author_id, :integer

але тепер, коли ви створюєте оператор pripada_то, вам доведеться його модифікувати, тому тепер вам доведеться зателефонувати

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

1
Чи не потрібно мені додавати індекс?
caarlos0

1
Так, вам потрібно буде створити індекс під час міграції.
Том Гаррісон

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

хм зрозумів. Велике спасибі!
caarlos0

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

251

Для рейок 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.


Чи дозволить початкове визначення нульових значень? Якщо ні, то чи знаєте ви мінливу альтернативу?
Vorpulus Lyphane

5
Це визначення дозволяє nulls. Щоб їх не допустити, додайте звичайний варіант null: false.
Ашитака

Дякую. Для "Початкового визначення", я думаю, що "індекс: істина" не потрібен. Я отримую таку ж зміну схеми з або без неї. Не звертай уваги; щойно побачив вашу записку наприкінці.
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
О, я цього не помічав. Ну, це було дуже корисно to.me. :)
бон

2
Я майже відмовився від надії, коли побачив це! Дякую @ecoologic!
Ден Вільямс

2
@ecoologic, лише одне, що ви можете додати, add_foreign_key - це лише рейки 4.2+. ;)
Ден Вільямс

4
Я не впевнений, що вам потрібен references: :usersваріант у add_referenceдзвінку. Я не бачу це документально зафіксовано в документах, і, здається, він працює на моєму кінці без цього.
jakecraige

87

У рейках 4 при використанні postgresql та gem 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дорогоцінний камінь у повному обсязі не сумісний з рейками 5+, але цю функціональність пропонують дорогоцінний камінь schema_auto_foreign_keys (частина schema_plus), сумісний з рейками 5.


28
а якщо ви використовуєте create_table:t.references :author, references: :users
Михайло Радіонов

2
Якщо додати відповідь @ MichaelRadionov до вашої відповіді, це зробить її ідеальною.
toxaq

2
Я дивився джерело Rails 4.1, і не можу знайти жодних доказів, які :referencesнасправді нічого не роблять.
jes5199

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/isissue/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}
множини

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