What determines if rails includes id: :serial in a table definition?

萝らか妹 提交于 2019-12-04 23:43:30

When you run rails db:migrate:reset as opposed to rails db:reset, the database schema is not loaded from schema.rb but is instead reconstructed from all of your migrations. In migrations and schema files you do not need to specify an id field, one is provided by default. However, starting with Rails 5.1, the default size of the id field was increased from INT to BIGINT for MySQL and from SERIAL to BIGSERIAL for PostgreSQL. So probably there is some interaction between your migrations, schema.rb, and the actual schema in the database that is causing the id field to be treated as default (and omitted) in some cases and be explicitly specified in others, just due to the change in the default size. It's hard to guess at the source of the problem without seeing all the relevant files.

The answer is simply rails 5.0 vs 5.1 migrations. I had previously thought that the project started in 5.1, so I didin't test this. But then I dug deeper and discovered it started in 5.0, and experimentation shows that's the answer.

5.0, no id specified

class SerialIdTest < ActiveRecord::Migration[5.0]
  def change
    create_table "test" do |t|
      t.integer "foo_id"
      t.string "foo_role"
    end
  end
end
create_table "test", id: :serial, force: :cascade do |t|
  t.integer "foo_id"
  t.string "foo_role"
end
# \d test
                                   Table "public.test"
      Column      |       Type        |                       Modifiers                       
------------------+-------------------+-------------------------------------------------------
 id               | integer           | not null default nextval('test_id_seq'::regclass)
 foo_id   | integer           | 
 foo_role | character varying | 
Indexes:
    "test_pkey" PRIMARY KEY, btree (id)

5.1, no id specified

class SerialIdTest < ActiveRecord::Migration[5.1]
  def change
    create_table "test" do |t|
      t.integer "foo_id"
      t.string "foo_role"
    end
  end
end
create_table "test", force: :cascade do |t|
  t.integer "foo_id"
  t.string "foo_role"
end
# \d test
                                   Table "public.test"
      Column      |       Type        |                       Modifiers                       
------------------+-------------------+-------------------------------------------------------
 id               | bigint            | not null default nextval('test_id_seq'::regclass)
 foo_id   | integer           | 
 foo_role | character varying | 
Indexes:
    "test_pkey" PRIMARY KEY, btree (id)

5.1, id serial specified

class SerialIdTest < ActiveRecord::Migration[5.1]
  def change
    create_table "test", id: :serial do |t|
      t.integer "foo_id"
      t.string "foo_role"
    end
  end
end
create_table "test", id: :serial, force: :cascade do |t|
  t.integer "foo_id"
  t.string "foo_role"
end
# \d test
                                   Table "public.test"
      Column      |       Type        |                       Modifiers                       
------------------+-------------------+-------------------------------------------------------
 id               | integer           | not null default nextval('test_id_seq'::regclass)
 foo_id   | integer           | 
 foo_role | character varying | 
Indexes:
    "test_pkey" PRIMARY KEY, btree (id)
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!