我对如何生成属于另一个模型的模型感到困惑。我的书使用以下语法将Micropost与用户相关联:
rails generate model Micropost user_id:integer
但http://guides.rubyonrails.org/表示要这样做:
rails generate model Micropost user:references
这两个生成的迁移是不同的。另外,对于前者,rails如何知道这user_id
是外键引用user
?谢谢!
我对如何生成属于另一个模型的模型感到困惑。我的书使用以下语法将Micropost与用户相关联:
rails generate model Micropost user_id:integer
但http://guides.rubyonrails.org/表示要这样做:
rails generate model Micropost user:references
这两个生成的迁移是不同的。另外,对于前者,rails如何知道这user_id
是外键引用user
?谢谢!
Answers:
运行迁移时,两者都会生成相同的列。在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
列上添加索引。
Rails如何知道
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
add_foreign_key
的选项替换了action ,这意味着。现在是这样。当前没有有关该选项的文档,因此这只是我的假设。foreign_key: true
t.references
index: true
t.references :user, foreign_key: true
foreign_key
add_reference
操作有一个: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`
add_foreign_key
已将其放入ActiveRecord。