bgrommes
bgrommes

Reputation: 65

How to migrate the database when renaming an ActiveRecord model that is a subclass of a base class?

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

Answers (2)

James EJ
James EJ

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

deefour
deefour

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

Related Questions