使用user生成模型:references vs user_id:integer

sta*_*ord 170 ruby-on-rails

我对如何生成属于另一个模型的模型感到困惑.我的书使用此语法将Micropost与User关联:

rails generate model Micropost user_id:integer
Run Code Online (Sandbox Code Playgroud)

但是http://guides.rubyonrails.org/说这样做:

rails generate model Micropost user:references
Run Code Online (Sandbox Code Playgroud)

这些2产生的迁移是不同的.另外,对于前者,rails如何知道这user_id是一个外键引用user?谢谢!

Jon*_* M. 187

运行迁移时,两者都将生成相同的列.在rails控制台中,您可以看到这种情况:

:001 > Micropost
=> Micropost(id: integer, user_id: integer, created_at: datetime, updated_at: datetime)
Run Code Online (Sandbox Code Playgroud)

第二个命令belongs_to :user在Micropost模型中添加了一个关系,而第一个命令则没有.指定此关系后,ActiveRecord将假定外键保留在user_id列中,并且它将使用命名的模型User来实例化特定用户.

第二个命令还在新user_id列上添加索引.


ill*_*ist 42

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
Run Code Online (Sandbox Code Playgroud)

关键字belongs_tohas_many确定这些模型之间的关系并声明user_idUser模型的外键.

后面的命令在模型中rails generate model Micropost user:references添加行belongs_to :user,Micropost并在此声明为外键.

FYI
使用前一种方法声明外键只允许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
Run Code Online (Sandbox Code Playgroud)

现在外键设置在数据库级别.你可以生成合适的EER图表. 在此输入图像描述

  • 似乎最新的 Rails 生成器将 `add_foreign_key` 操作替换为 `t.references` 行的选项 `foreign_key: true`,这意味着 `index: true`。所以现在是`t.references :user, foreign_key: true`。目前没有关于 `foreign_key` 选项的文档可用,所以这只是我的假设。 (2认同)

Kru*_*ule 15

对于前者,约定优于配置.当您引用另一个表时,Rails默认为

 belongs_to :something
Run Code Online (Sandbox Code Playgroud)

是要找something_id.

references,或者belongs_to实际上是用较少的怪癖编写前者的新方法.

重要的是要记住,它不会为您创建外键.为此,您需要使用以下任一方式明确设置:

t.references :something, foreign_key: true
t.belongs_to :something_else, foreign_key: true
Run Code Online (Sandbox Code Playgroud)

或(注意复数):

add_foreign_key :table_name, :somethings
add_foreign_key :table_name, :something_elses`
Run Code Online (Sandbox Code Playgroud)