Міграція рейки: t.references з альтернативною назвою?


121

Тож у мене є такий створений таблиця для курсів у школі:

create_table :courses do |t|
  t.string :name
  t.references :course
  t.timestamps
end

але я хочу, щоб він посилався на два інші курси, такі як:

has_many :transferrable_as # A Course
has_many :same_as          # Another Course

Чи можу я сказати наступне?

t.references :transferrable_as, :as=> :course

Відповіді:


161

Ви можете зробити це все в початковому визначенні міграції / стовпця (принаймні, зараз у Rails 5):

t.references :transferable_as, index: true, foreign_key: {to_table: :courses}
t.references :same_as, index: true, foreign_key: {to_table: :courses}

10
Це працює на Rails 5.1, і жодна з інших пропозицій не робить. Це набагато чистіше, і почуває себе правильно.
Stephenmurdoch

2
Я використовую Rails 5.1.4, але він не працює. Коли я вказую foreign_keyпараметр у створенні таблиці таким чином, виникає помилка, кажучи, що сама таблиця, яку я створюю, не існує ... Тож я підозрюю, що вона не підтримується офіційним API.
Quv

3
Я також читав, що indexвже додано до іноземних ключів станом на Rails stackoverflow.com/questions/39769981/…
Джонатан Рейєс,

98

Ви можете це зробити так:

create_table :courses do |t|
  t.string :name
  t.references :transferrable_as
  t.references :same_as
  t.timestamps
end

або використовувати t.belongs_toпсевдонім дляt.references

Ви не можете додати foreign_key: trueдо цих двох посилальних рядків. Якщо ви хочете позначити їх як зовнішні ключі на рівні бази даних, вам потрібно виконати міграцію з цим:

add_foreign_key :courses, :courses, column: :transferrable_as_id
add_foreign_key :courses, :courses, column: :same_as_id

Оновлення

У Rails 5.1 і вище ви можете додати зовнішній ключ при міграції в create_tableблок так:

create_table :courses do |t|
  t.string :name
  t.references :transferrable_as, foreign_key: { to_table: 'courses' }
  t.references :same_as, foreign_key: { to_table: 'courses' }
  t.timestamps
end

5
Частина про те, що я не маю змоги додати foreign_key: trueдо рядків посилань, те, що мене спонукало. Додавши add_foreign_keyта вказавши назву стовпця для тих, хто зробив свою справу.
Меттью Кларк

Це спрацьовує нестандартно в Rails? Згідно stackoverflow.com/a/22384289/239657 , для цього потрібен schema_plusдорогоцінний камінь. Документи add_reference Rails не згадують про: параметри посилань.
Бені Чернявський-Паскін

1
Я не слідкую за тим, для чого цей references:варіант (на відміну від того, t.referencesчи не це буде актуальним лише на рівні моделі, зважаючи на увагу іноземних ключів add_foreign_key?
MCB

1
@MCB t.referencesкаже "додати в цю таблицю поле, яке є первинним ключем іншої таблиці". references:Опція вказує , що якась таблиця це первинний ключ (потрібно , якщо не ясно , по імені поля). add_foreign_keyФункція повідомляє бази даних для примусової посилальної цілісності тут.
Тобі 1 Кенобі

2
@MCB після закінчення цього часу я розумію, що ти був правильний весь час. Ваш перший коментар вище абсолютно правильний - add_foreign_keyрядки дбають про інформування бази даних, що є зовнішнім ключем від чого. references:Параметр не робить нічого.
Toby 1 Kenobi

13

Я думаю, що цей потік має інший спосіб Rails-ish: Скелефони ActiveRecord: два стовпчики одного типу даних

Під час міграції:

t.belongs_to: переносимий_as

t.belongs_to: той же_as


1
але як db знає, до якого зовнішнього ключа зв’язати таблицю? Я намагаюся це зробити з базою даних Postgres, і це дає мені помилку PG::UndefinedTable: ERROR, намагаючись додати обмеження зовнішнього ключа до таблиці, яка не існує.
Toby 1 Kenobi

У разі , якщо хто - то цікаво, belongs_toце просто псевдонім , щоб referencesі тому має точно таку ж функціональність.
Jason Swett

11

Як додана відповідь на це питання - Модель повинна мати наступний рядок для завершення асоціації:

    belongs_to :transferrable_as, class_name: "Course"
    belongs_to :same_as, class_name: "Course"

3

Я не думаю, що referencesприймає :asваріант, але ви можете створювати свої стовпці вручну ...

create_table :courses do |t| 
  t.string  :name 
  t.integer :course1_id
  t.integer :course2_id 
  t.timestamps 
end 
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.