Reputation: 65
How can I write a Rails migration to rename an ActiveRecord subclass when the models are stored in the database using single table inheritance (STI)? The only thing I can think of is to use a raw sql update statement to change the value of type column value from the old subtype name to the new one.
Upvotes: 2
Views: 995
Reputation: 2144
Rails 4 lets you define a reversible
migration for @deefour's answer:
def change
rename_sti_type :table_name, 'Namespace::OldSubclass', 'Namespace::NewSubclass'
end
def rename_sti_type(table_name, old_type, new_type)
reversible do |dir|
dir.up { execute "UPDATE #{table_name} SET type = '#{new_type}' WHERE type = '#{old_type}'" }
dir.down { execute "UPDATE #{table_name} SET type = '#{old_type}' WHERE type = '#{new_type}'"}
end
end
You could generalise this into a change_data(table, field, old_value, new_value)
method; but be mindful that if the up migration sets the type/field to a new_value
which is already in use, then the down migration will also change existing rows which already had new_value
value into old_value
.
Upvotes: 2
Reputation: 35360
You can use execute
to run raw queries in the migrations
class YourMigration < ActiveRecord::Migration
def up
execute "UPDATE table_name SET type = 'Namespace::NewSubclass' WHERE type = 'Namespace::OldSubclass'"
end
def down
execute "UPDATE table_name SET type = 'Namespace::OldSubclass' WHERE type = 'Namespace::NewSubclass'"
end
end
Upvotes: 7