我对如何生成属于另一个模型的模型感到困惑。我的书使用这种语法将Micropost与User关联起来:
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是引用用户的外键?谢谢!
在运行迁移时,两者都将生成相同的列。在rails控制台中,你可以看到情况是这样的:
:001 > Micropost
=> Micropost(id: integer, user_id: integer, created_at: datetime, updated_at: datetime)
第二个命令在Micropost模型中添加belongs_to:用户关系,而第一个命令则没有。当指定此关系时,ActiveRecord将假定外键保存在user_id列中,并使用名为User的模型来实例化特定的用户。
第二个命令还在新的user_id列上添加了一个索引。
rails如何知道user_id是一个引用用户的外键?
Rails本身并不知道user_id是一个引用用户的外键。在第一个命令中,rails生成模型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声明为用户模型的外键。
后面的命令rails生成模型Micropost user:references在Micropost模型中添加了belongs_to:user行,并在此声明为外键。
仅供参考
使用前一种方法声明外键只让Rails知道模型/表之间的关系。数据库不知道该关系。因此,当您使用像MySql Workbench这样的软件生成EER图时,您会发现在模型之间没有绘制关系线程。就像下面的图片
然而,如果你使用后面的方法,你会发现你的迁移文件看起来像:
def change
create_table :microposts do |t|
t.references :user, index: true
t.timestamps null: false
end
add_foreign_key :microposts, :users
现在外键被设置在数据库级别。你可以生成正确的EER图。
对于前者,约定优于配置。使用引用另一个表时,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`
在运行迁移时,两者都将生成相同的列。在rails控制台中,你可以看到情况是这样的:
:001 > Micropost
=> Micropost(id: integer, user_id: integer, created_at: datetime, updated_at: datetime)
第二个命令在Micropost模型中添加belongs_to:用户关系,而第一个命令则没有。当指定此关系时,ActiveRecord将假定外键保存在user_id列中,并使用名为User的模型来实例化特定的用户。
第二个命令还在新的user_id列上添加了一个索引。