сгенерировать модель, используя user: reference против user_id: integer

177

Я запутался в том, как создать модель, принадлежащую другой модели. Моя книга использует этот синтаксис, чтобы связать Micropost с пользователем:

rails generate model Micropost user_id:integer

но http://guides.rubyonrails.org/ говорит сделать это так:

rails generate model Micropost user:references

Миграции, порожденные этими двумя, различны. Кроме того, для первых, как rails узнает, что user_idэто ссылка на внешний ключ user? Спасибо!

stackOverlord
источник

Ответы:

190

Оба будут генерировать одинаковые столбцы при запуске миграции. В консоли rails вы можете видеть, что это так:

:001 > Micropost
=> Micropost(id: integer, user_id: integer, created_at: datetime, updated_at: datetime)

Вторая команда добавляет belongs_to :userотношение в вашу модель Micropost, тогда как первая - нет. Когда эта связь указана, ActiveRecord будет предполагать, что внешний ключ хранится в user_idстолбце, и будет использовать модель, названную Userдля создания экземпляра конкретного пользователя.

Вторая команда также добавляет индекс для нового user_idстолбца.

Джон М.
источник
1
Можно ли сгенерировать модель со ссылками на две таблицы
praveenkumar
Обратите внимание, что он не добавляет ассоциацию has_many для другой модели (пользователя), которую вы также можете добавить.
Sv1
45

откуда рельсы знают, что user_idэто ссылка на внешний ключ user?

Сам Rails не знает, что user_idэто ссылка на внешний ключ user. В первой команде rails generate model Micropost user_id:integerон только добавляет столбец, user_idоднако rails не знает, как использовать col. Вам нужно вручную поставить линию в Micropostмодели

class Micropost < ActiveRecord::Base
  belongs_to :user
end

class User < ActiveRecord::Base
  has_many :microposts
end

ключевые слова belongs_toи has_manyопределяют отношения между этими моделями и объявляют user_idв качестве внешнего ключа для Userмодели.

Более поздняя команда rails generate model Micropost user:referencesдобавляет строку belongs_to :userв Micropostмодель и тем самым объявляет как внешний ключ.

К вашему сведению
Объявление внешних ключей с использованием предыдущего метода позволяет только Rails знать о взаимоотношениях моделей / таблиц. База данных неизвестна об отношениях. Поэтому, когда вы генерируете диаграммы EER с помощью программного обеспечения, подобного тому, MySql Workbenchвы обнаружите, что между моделями не нарисованы потоки взаимосвязей. Как на следующей картинке введите описание изображения здесь

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

def change
    create_table :microposts do |t|
      t.references :user, index: true

      t.timestamps null: false
    end
    add_foreign_key :microposts, :users

Теперь внешний ключ установлен на уровне базы данных. и вы можете создавать правильные EERдиаграммы. введите описание изображения здесь

иллюзионист
источник
1
Похоже, что последний генератор Rails заменил add_foreign_keyдействие опцией foreign_key: trueна t.referencesстроку, что подразумевает index: true. Так и сейчас t.references :user, foreign_key: true. В настоящее время нет документации по этой foreign_keyопции, так что это только мое предположение.
Франклин Ю
О, у add_referenceдействия есть :foreign_keyопция, которая добавляет соответствующее ограничение внешнего ключа . Я думаю, что эта опция будет делать то же самое при создании таблицы.
Франклин Ю
Как вы экспортируете свой ruby ​​db в верстак? не могли бы вы ответить на этот вопрос здесь: stackoverflow.com/questions/42982921/…
Krawalla
Имеет ли add_foreign_key :microposts, :users какое-либо значение для Rails?
Линус
17

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

 belongs_to :something

это искать something_id.

references, или belongs_toна самом деле более новый способ написания первого с несколькими причудами.

Важно помнить, что он не будет создавать внешние ключи для вас. Для того, чтобы сделать это, вам нужно явно установить его, используя:

t.references :something, foreign_key: true
t.belongs_to :something_else, foreign_key: true

или (обратите внимание на множественное число):

add_foreign_key :table_name, :somethings
add_foreign_key :table_name, :something_elses`
Krule
источник
1
Можете ли вы объяснить, что вы имеете в виду, говоря, что ссылки не создадут для вас внешние ключи. Чем он отличается от первой команды, использующей user_id: integer напрямую?
Shailesh
Это не так, за исключением случая, когда вы используете :polymorphicопцию (что, IMHO, в большинстве случаев не очень хорошая идея). Если вы хотите использовать внешние ключи в ActiveRecord, используйте иностранец .
Круле
1
@Krule Теперь add_foreign_keyсделал это в ActiveRecord.
Франклин Ю