1. Rails 5.1 new default BIGINT primary key sort of ruins existing apps (with fix!)

    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 INTs 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 BIGINTs. 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!