On Rails Migrations Continued
Posted by Richard White Sat, 04 Feb 2006 02:06:00 GMT
Encountered another issue with migrations today when trying to do the followingadd_column :appt_service_logins, :id, :primary_keyThis threw an error when running rake migrate against my PostgreSQL DB that essentially boiled down to migrations trying to run the following SQL
ALTER TABLE appt_service_logins ADD idObviously missing the datatype for the column. I tracked this down to type_to_sql returning nil. This was because def native_database_types define a Hash where primary key does not map to another Hash with a :name key (see previous post). Therefore the following in def type_to_sql would return nil since it specifically looks for the value using the :name key.
def type_to_sql(type, limit = nil) #:nodoc:
native = native_database_types[type]
limit ||= native[:limit]
column_type_sql = native[:name]
column_type_sql << "(#{limit})" if limit
column_type_sql
endTo get around this I modified def type_to_sql to use the native value if column_type_sql was nil.
def type_to_sql(type, limit = nil) #:nodoc:
native = native_database_types[type]
limit ||= native[:limit]
column_type_sql = native[:name]
column_type_sql << "(#{limit})" if limit
if column_type_sql
column_type_sql
else
native
end
endI have no idea what the implications of such a change would be which is why I submitted this as a bug.
In the meantime since I was worried about the implications of changing def type_to_sql, I added a native database type of bigserial and am adding the column as a non-null bigserial and with a unique index.
Changes to postgre_extensions.rb:
def native_database_types
{
:primary_key => "bigserial primary key",
:string => { :name => "character varying", :limit => 255 },
:text => { :name => "text" },
:integer => { :name => "integer" },
:float => { :name => "float" },
:datetime => { :name => "timestamp" },
:timestamp => { :name => "timestamp" },
:time => { :name => "time" },
:date => { :name => "date" },
:binary => { :name => "bytea" },
:boolean => { :name => "boolean" },
:bigint => { :name => "int8" },
<strong>:bigserial => { :name => "bigserial" }</strong>
}
endIn self.up in the migration file:
add_column :appt_service_logins, :id, :bigserial, :null => false add_index :appt_service_logins, :id, :uniqueTo wrap up I attempted to put all of my changes into a Rails plugin so I wouldn’t have to put require ‘postgre_extensions’ at the top of each migration file as this fellow did but to no avail. I settled on just adding require ‘postgre_extensions’ to the bottom of my environment.rb. If you know of a better way to do this, let me know.