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

可紊 提交于 2019-12-21 07:48:08

问题


I'm working with an existing rails app, using postgresql. Its schema.rb file has id: :serial for many, but not all, tables:

create_table "foos", id: :serial, force: :cascade do |t|

When I run rails db:migrate:reset, id: :serial is removed. We are all on the same version of postgres, but different OSes. I haven't exhaustively tested the behavior between machines, but I think there is a difference between machines.

The rails version is the same as it was when the project started.

The project did start with sqlite3. When I switch to that and regenerate the file, same behavior.

What could cause this option to be removed in my environment?

here's some code that is probably relevant:

  • https://github.com/rails/rails/blob/b2eb1d1c55a59fee1e6c4cba7030d8ceb524267c/activerecord/lib/active_record/connection_adapters/postgresql/column.rb#L15-L21
  • https://github.com/rails/rails/blob/b2eb1d1c55a59fee1e6c4cba7030d8ceb524267c/activerecord/lib/active_record/connection_adapters/postgresql/schema_dumper.rb#L26-L42

update

  • I just tried rails db:migrate:reset on colleague's machines, and I was wrong! their environments also remove id: :serial.
  • I looked closer at recent migrations from a colleague, and the most recent one did not create id: :serial in schema.rb either.

回答1:


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.




回答2:


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)


来源:https://stackoverflow.com/questions/54598531/what-determines-if-rails-includes-id-serial-in-a-table-definition

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!