我正在使用一个现有的rails应用程序,使用postgresql。它的schema.rb文件对许多表(但不是所有表)都有id: :serial
:
create_table "foos", id: :serial, force: :cascade do |t|
当我运行rails db:migrate:reset
时,id: :serial
将被删除。我们都使用相同版本的postgres,但操作系统不同。我还没有详尽地测试过机器之间的行为,但我认为机器之间是有区别的。
rails版本与项目启动时相同。
该项目确实是从sqlite3开始的。当我切换到那个并重新生成文件时,同样的行为。
是什么原因导致此选项在我的环境中被删除?
以下是一些可能相关的代码:
- 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
更新
- 我刚刚在同事的机器上尝试了
rails db:migrate:reset
,但我错了!它们的环境也去除了CCD_ 5 - 我仔细查看了一位同事最近的迁移,最近的迁移也没有在schema.rb中创建
id: :serial
当您运行rails db:migrate:reset
而不是rails db:reset
时,数据库模式不是从schema.rb
加载的,而是从所有迁移中重建的。在迁移和模式文件中,您不需要指定id
字段,默认情况下会提供一个字段。然而,从Rails 5.1开始,MySQL的id字段的默认大小从INT
增加到了BIGINT
,PostgreSQL的id字段从SERIAL
增加到BIGSERIAL
。因此,您的迁移schema.rb
和数据库中的实际模式之间可能存在一些交互,这导致id字段在某些情况下被视为默认字段(并被省略),而在其他情况下被显式指定,只是由于默认大小的变化。如果不查看所有相关文件,很难猜测问题的根源。
答案只是rails 5.0与5.1迁移。我之前认为该项目始于5.1,所以我没有对此进行测试。但后来我更深入地研究,发现它始于5.0,实验表明这就是答案。
5.0,未指定id
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,未指定id
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序列
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)