Wednesday 2 March 2011

Gotcha: migrations with trailing commas

Trailing commas are bad m'kay?

I had a pretty standard migration, which included something like the following two lines:

    create_table :my_widgets do |t|
      t.string :name, :colour, :flavour
      t.integer :supplier_id
      t.integer :height, :width, :depth,    # note this extra comma...

      t.timestamps
    end

Looked fine at a casual glance, ran just fine - no hiccups. Been using it on dev for a week or so now... no problems... Only noticed an issue when I glanced at db/schema.rb

  create_table "service_report_stats", :force => true do |t|
    t.string   "name"
    t.string   "colour"
    t.string   "flavour"
    t.integer  "supplier_id"
    t.integer  "height"
    t.integer  "width"
    t.integer  "depth"
    t.datetime "created_at"
    t.datetime "updated_at"
    t.integer  "#<ActiveRecord::ConnectionAdapters::TableDefinition:0xb5c35504>" # WTF???
  end

Something seriously wrong with that last "integer" column... mysql shows that yes, that is actually the column's real name:

+-----------------------------------------------------------------+----------+------+-----+---------+----------------+
| Field                                                           | Type     | Null | Key | Default | Extra          |
+-----------------------------------------------------------------+----------+------+-----+---------+----------------+
| id                                                              | int(11)  | NO   | PRI | NULL    | auto_increment |
| supplier_id                                                     | int(11)  | YES  |     | NULL    |                |
.... etc ...
| created_at                                                      | datetime | YES  |     | NULL    |                |
| updated_at                                                      | datetime | YES  |     | NULL    |                |
| #<ActiveRecord::ConnectionAdapters::TableDefinition:0xb5c35504> | int(11)  | YES  |     | NULL    |                |
+-----------------------------------------------------------------+----------+------+-----+---------+----------------+

Right now I have NFI how to actually remove the column... because trying:
alter table my_widgets drop column #<ActiveRecord::ConnectionAdapters::TableDefinition:0xb5c35504>;
Just results in: ERROR 1064 (42000): You have an error in your SQL syntax; , and it won't accept it if I put it in quotes either... so the column currently remains as is.

Luckily I was playing with a branch of the real system - so it's only my dev-box's code that has been mucked about... and I can change the migration before anybody else uses it... but this is seriously weird behaviour on Rails' part. Not a raised exception or even a raised eyebrow... it sailed right through and is continuing on regardless.

To actually fix it, I had to create a migration with the following:

    remove_column :my_widgets,  "#<ActiveRecord::ConnectionAdapters::TableDefinition:0xb5c35504>"

Seems the Rails itself can tell mysql about a weirdly-named column somehow. I'd still like to know the actual SQL involved...

No comments: