Search code examples
ruby-on-railspostgresqlrails-migrations

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


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:

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.

Solution

  • 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)