Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I create a reversible migration helper in rails?

I find myself having to execute very similar sql statements (with maybe 1 param besides the table name) on several tables on a rails app. As a result, I'm getting lots of similarly looking migrations, like this one:

class DoSomeSQLOnUser < ActiveRecord::Migration
  def up
    execute('some long sql that alters the user.field1')
    execute('some long sql that alters the user.field2')
  end

  def down
    execute('some sql that undoes the changes')
  end
end

Then I have the same thing for clients, sales, etc.

I would like to extend ActiveRecord::Migration so that I can do this instead:

class DoSomeSQLOnUser < ActiveRecord::Migration
  def change
    do_custom_thing_on :users, :field1
    do_custom_thing_on :users, :field2
  end
end

How can I do that? I think I know how to do it when the operations are separated into up and down, like this:

class DoSomeSQLOnUser < ActiveRecord::Migration
  def up
    do_custom_thing_on :users, :field1
    do_custom_thing_on :users, :field2
  end
  def down
    undo_custom_thing_on :users, :field1
    undo_custom_thing_on :users, :field2
  end
end

But doing it so that the change is "reversible" escapes me.

like image 628
kikito Avatar asked Jun 07 '13 11:06

kikito


2 Answers

It doesn't seem to be a official supported way to do this, so probably you'll need to open the class ActiveRecord::Migration::CommandRecorder and record the new method and its inverted version.

Find the definition of the class at activerecord/lib/active_record/migration/command_recorder.rb.

like image 198
blat Avatar answered Sep 24 '22 18:09

blat


In Rails 4 there is a reversible helper method, which you can use like this:

def change
  do_custom_thing_on :users, :field1
  do_custom_thing_on :users, :field2
end

def do_custom_thing_on(table, field)
  reversible do |dir|
    dir.up { execute "some long sql to alter #{field} on #{table}"}
    dir.down { execute "some long sql to undo #{field} on #{table}"}
  end
end
like image 34
James EJ Avatar answered Sep 21 '22 18:09

James EJ