You can do it in one go quite easily using the USING clause of ALTER TABLE:
The optional USING
clause specifies how to compute the new column value from the old; if omitted, the default conversion is the same as an assignment cast from old data type to new.
A simple SQL type cast would leave you with the strings 'true'
and 'false'
so you do want to add a USING. I'd bypass AR and do it by hand:
connection.execute(%q(
alter table users
alter column active
type text
using case when active then 'active' else 'inactive' end
))
The important part for you is the using case ...
part at the end. You can use that together with the usual AR-ish change_column
stuff by tricking AR into doing The Right Thing:
class ChangeColumnTypeInUsers < ActiveRecord::Migration
def up
change_column :users, :active, "text using case when active then 'active' else 'inactive' end"
end
def down
change_column :users, :active, "boolean using active = 'active'"
end
end
Note that I'm using text
as the column type. Rails will using varchar(255)
inside the database when you say :string
without a limit, that's pretty pointless with PostgreSQL as it handles the storage for all the string types pretty much the same internally, the length restrictions on char(n)
and varchar(n)
actually make them more expensive to use than text
. Then only time :string
makes sense with PostgreSQL is when you have a reason to include a specific :limit
(and then a text
column with a CHECK
constraint on the length would make more sense but AR is too dumb to know about "advanced" things like CHECK
constraints).