TL;DR
Run bin/rails db:schema:dump
in development to get a new schema.rb
file built that explictly defines :integer
as the data type for all id
columns.
What’s going on
I just upgraded our app to Rails 5.1 but ran into a problem when trying to build and run the test suite on our CI:
ActiveRecord::MismatchedForeignKey: Column `role_id` on table
`authorizations` has a type of `int(11)`. This does not match
column `id` on `roles`, which has type `bigint(20)`. To resolve
this issue, change the type of the `role_id` column on
`authorizations` to be :integer. (For example `t.integer role_id`).
After some research I found that this message was added specifically for 5.1 when you try to have a new BIGINT
column be a member of a foreign key that’s still of type INT
.
The problem is that the schema file didn’t define what data type your id
columns should be because there was no need to: everything was always INT
and that’s all it would ever be. Going forward, however, the default is BIGINT
so when Rails 5.1 sees the datatype-less schema file it happily makes all the id
columns BIGINT
, but all your foreign keys are defined in the schema with t.integer
so they’re plain INT
s still. Ugh.
I figured maybe there was new syntax for the schema file that would explictly tell Rails that the id
column should be an INT
and not use the default of BIGINT
. I ran a bin/rails db:schema:dump
and sure enough for every table there’s a new parameter:
create_table "authorizations", id: :integer, force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|
Notice that id: :integer
is new.
If you want to take advantage of BIGINT
then you would need to migrate all existing id
and foreign *_id
columns to be BIGINT
s. But, this means dropping foreign keys altogether, upgrade column types, then re-adding your foreign keys (or maybe tell your database to ignore foreign key relationships while you migrate all these datatypes, but I haven’t tried that technique). You’ll need to take your site offline to do this. That wasn’t worth the hassle for us, and we’re nowhere near id 4,294,967,295 so we should be good for a while.
If future me is reading this after getting our 4 billionth user: it seemed like a reasonable tradeoff at the time!