← Home

Allow custom column types in your Rails migrations

There's a workaround that allows you to append column definitions at the end (!) of your table definition:


class CreateForms <ActiveRecord::Migration
  def self.up
    create_table :cards do |t|
      # ...
      t.columns << 'value varbinary(255)'
    end
  end
end

Obviously this might not be what everbody really wants. If you're like me you prefer to keep your stuff tidy ... and the column order in my tables therefor definitely matters.

No problem: Rails plugins to the rescue here. After some digging through the ActiveRecord source it turns out that it's pretty easy to convince Rails to accept not only predefined column types (like :string) but also wildly arbitrary strings.

So, how about the following code?


ActiveRecord::ConnectionAdapters::SchemaStatements.module_eval do
  def type_to_sql_with_custom_type(type, *params)
    return type unless native_database_types.has_key? type
    type_to_sql_without_custom_type(type, *params)
  end
  alias_method_chain :type_to_sql, :custom_type
end

SchemaStatements#type_to_sql tries to look up the column type (like :string) and throws an error if it doesn't find it in the native_database_types. What we're doing with that unbelievable hack above is nothing else than silently navigate our custom column definition around this face check so that it gets inserted into the resulting SQL code literally.

So with this (not so) ugly hack plugin applied you can now do things like this:


class CreateForms <ActiveRecord::Migration
  def self.up
    create_table :cards do |t|
      t.column :value, 'varbinary(255)'
    end
  end
end

... and use whatever column order you like :-)

Go, get it

Yes, you can download this stuff. Standing in your Rails home directory point your script/plugin installer to:


script/plugin install http://svn.artweb-design.de/stuff/rails/migration_custom_column_types/