Rails 迁移将数据类型从 :bigint 更改为 :integer

Rails Migration Changes Datatype from :bigint to :integer

我最近创建了一个迁移来更新一些数据,在我 运行 它之后,迁移将我的一堆 schema.rb 列定义从 :bigint 更改为 :integer

我过去曾多次注意到这一点。有时迁移会将它们从 :bigint 更改为 :integer,其他时候反之亦然。

为什么会发生这种情况,我该如何预防?我想将它们保留为 :bigint

我 运行 Ruby Rails 7.0.2.3 和 PostgreSQL 14.2

谢谢

不确定原因,但据我所知,这个问题出现在 RoR 版本 3 或 4 中。 您需要使用这样的格式

tbl.column :really_big_int, :bigint

我想通了....

问题: 数据库类型与模式不同,因此迁移时 运行,rails 实现了实际数据库中的类型不同,所以它为我更新了架构。

为什么我们的类型不同?

我从 Heroku 中提取了一个数据库转储,以便在本地复制一个我无法复制的问题(它只发生在 Heroku 上的那个数据集)。这样做后,这个问题就开始了。

问题是 Heroku 是 运行ning Postgres 13.6,并且出于某种原因,该数据库中的列类型是 integer

本地我是 运行ning Postgres 14.2,本地类型是 bigint

如果迁移没有任何改变,为什么要更新 schema.rb 文件?

发生这种情况是因为 db:schema:dump 是自动迁移后的 运行。这发生在 Rails.

中的 database.rake 文件中

来源:https://github.com/rails/rails/blob/main/activerecord/lib/active_record/railties/databases.rake#L105

换句话说,迁移得到 运行,然后 Active Record 自动转储模式。

由于数据类型不同,新模式转储与原始模式不同。因此 schema.rb 文件已更新(如果您使用的是 annotate gem,则还更新任何模型文件)。

我怎么知道的?

使用 psql 登录数据库并检查。

  • 本地:psql -h localhost
  • Heroku:heroku pg:psql -a your-app-name

然后检查 table:

  • \d table_name

你会得到这样的东西:

                                          Table "public.account_invitations"
    Column     |              Type              | Collation | Nullable |                     Default
---------------+--------------------------------+-----------+----------+-------------------------------------------------
 id            | bigint                         |           | not null | nextval('account_invitations_id_seq'::regclass)
 account_id    | integer                        |           | not null |
 invited_by_id | integer                        |           |          |
 token         | character varying              |           | not null |

在那里您可以看到列类型。在本地,它们是 bigint 使用 Postgres 14.2,但在 Heroku 上,它们是 integer 使用 Postgres 13.6。

当我拉下一个转储时,我从那个转储中恢复了本地数据库,这改变了数据库与模式中的内容。

修复: 恢复了我的数据库的原始版本,运行 迁移,没有对架构进行任何更改。

如何检验这个理论... 进入数据库控制台并将列从 integer 更改为 bigint,反之亦然。然后 运行 迁移。您会注意到您的架构文件已更新,即使您的迁移可能与这些列无关。