我对如何生成一个属于另一个模型的模型感到困惑。我的书使用这种语法将 Micropost 与用户相关联:
rails generate model Micropost user_id:integer
但 https://guides.rubyonrails.org/active_record_migrations.html#creating-a-standalone-migration 说要这样做:
rails generate model Micropost user:references
这两个产生的迁移是不同的。另外,对于前者,rails 是如何知道 user_id
是引用 user
的外键?谢谢!
运行迁移时,两者都将生成相同的列。在 rails 控制台中,您可以看到是这样的:
:001 > Micropost
=> Micropost(id: integer, user_id: integer, created_at: datetime, updated_at: datetime)
第二个命令在您的 Micropost 模型中添加 belongs_to :user
关系,而第一个命令没有。指定此关系后,ActiveRecord 将假定外键保存在 user_id
列中,并将使用名为 User
的模型来实例化特定用户。
第二个命令还在新的 user_id
列上添加索引。
rails 如何知道 user_id 是引用用户的外键?
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
在 Micropost
模型中添加行 belongs_to :user
并在此声明为外键。
https://i.stack.imgur.com/y6J0P.png
但是,如果您使用后一种方法,您会发现迁移文件如下所示:
def change
create_table :microposts do |t|
t.references :user, index: true
t.timestamps null: false
end
add_foreign_key :microposts, :users
https://i.stack.imgur.com/ew9UO.png
t.references
行的选项 foreign_key: true
替换了 add_foreign_key
操作,这意味着 index: true
。所以现在是t.references :user, foreign_key: true
。目前没有可用的 foreign_key
选项的文档,所以这只是我的假设。
add_reference
action 有一个 :foreign_key
选项,它添加适当的外键约束。我猜这个选项在创建表时会做同样的事情。
add_foreign_key :microposts, :users
对 Rails 有什么影响吗?
对于前者,约定优于配置。当您引用另一个表时,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`
:polymorphic
选项(恕我直言,在大多数情况下,这不是一个好主意)。如果要在 ActiveRecord 中使用外键,请使用 foreigner。
add_foreign_key
已进入 ActiveRecord。
不定期副业成功案例分享
:references
会在外键上创建索引,而手动创建列不会?