280

Is there an easy way to run a single migration? I don't want to migrate to a certain version I just want to run a specific one.

nan
  • 4,038
  • 4
  • 22
  • 23
  • Is this something that you ran once as a migration because it happened to be needed, then turns out to be a useful query that might need to get run a number of times? perhaps you should refactor the contents of the migration into a model or other object, then have the migration reference that new location. Then you can simply execute the new object at your lesure by invoking ruby on the command line. – Nathan Feger Apr 15 '09 at 22:09

11 Answers11

466

Assuming fairly recent version of Rails you can always run:

rake db:migrate:up VERSION=20090408054532

Where version is the timestamp in the filename of the migration.

Edit: At some point over the last 8 years (I'm not sure what version) Rails added checks that prevent this from running if it has already been run. This is indicated by an entry in the schema_migrations table. To re-run it, simply execute rake db:migrate:redo VERSION=20090408054532 instead.

grepsedawk
  • 3,055
  • 2
  • 24
  • 46
gtd
  • 15,952
  • 6
  • 45
  • 61
256

You can just run the code directly out of the ruby file:

rails console
>> require "db/migrate/20090408054532_add_foos.rb"
>> AddFoos.new.up

Note: Very old versions of rails may require AddFoos.up rather than AddFoos.new.up.

An alternative way (without IRB) which relies on the fact that require returns an array of class names:

script/runner 'require("db/migrate/20090408054532_add_foos.rb").first.constantize.up'

Note that if you do this, it won't update the schema_migrations table, but it seems like that's what you want anyway.

Additionally, if it can't find the file you may need to use require("./db/..." or try require_relative depending on your working directory

Orion Edwards
  • 113,829
  • 60
  • 223
  • 307
112

If you want to run a specific migration, do

$ rake db:migrate:up VERSION=20080906120000

If you want to run migrations multiple times, do

# use the STEP parameter if you need to go more than one version back
$ rake db:migrate:redo STEP=3

If you want to run a single migration multiple times, do

# this is super useful
$ rake db:migrate:redo VERSION=20080906120000

(you can find the version number in the filename of your migration)


Edit: You can also simply rename your migration file, Eg:

20151013131830_my_migration.rb -> 20151013131831_my_migration.rb

Then migrate normally, this will treat the migration as a new one (usefull if you want to migrate on a remote environment (such as staging) on which you have less control.

Edit 2: You can also just nuke the migration entry in the database. Eg:

rails_c> q = "delete from schema_migrations where version = '20151013131830'"
rails_c> ActiveRecord::Base.connection.execute(q)

rake db:migrate will then rerun the up method of the nuked migrations.

Benjamin Crouzier
  • 34,915
  • 36
  • 154
  • 219
  • Both "up" and "redo" didn't work for me, but deleting the row in schema_migrations was perfect. – cesoid Jul 26 '16 at 19:36
29

If you've implemented a change method like this:

class AddPartNumberToProducts < ActiveRecord::Migration
  def change
    add_column :products, :part_number, :string
  end
end

You can create an instance of the migration and run migrate(:up) or migrate(:down) on an instance, like this:

$ rails console
>> require "db/migrate/20090408054532_add_part_number_to_products.rb"
>> AddPartNumberToProducts.new.migrate(:down)
chibicode
  • 1,821
  • 3
  • 20
  • 24
18

This are the steps to run again this migration file "20150927161307_create_users.rb"

  1. Run the console mode. (rails c)
  2. Copy and past the class which is in that file to the console.

    class CreateUsers < ActiveRecord::Migration
      def change
        create_table :users do |t|
          t.string :name
          t.string :email
          t.timestamps null: false   end
        end
      end
    end
    
  3. Create an instance of the class CreateUsers: c1 = CreateUsers.new

  4. Execute the method change of that instance: c1.change
mbinette
  • 4,884
  • 3
  • 22
  • 31
rolph dzounga
  • 189
  • 1
  • 3
  • just require the file with the class, e.g. in the console: `require "./db/migrate/20150927161307_create_users.rb"` instead of copy & pasting. You can then run the class the same way by instantiating and calling the method defined in the class `CreateUsers.new.change`. – VinnyQ77 Feb 15 '20 at 00:06
  • perfect! Thank you – Nezir Oct 26 '20 at 18:17
14

As of rails 5 you can also use rails instead of rake

Rails 3 - 4

# < rails-5.0
rake db:migrate:up VERSION=20160920130051

Rails 5

# >= rails-5.0
rake db:migrate:up VERSION=20160920130051

# or

rails db:migrate:up VERSION=20160920130051
Graham
  • 6,577
  • 17
  • 55
  • 76
Deepak Mahakale
  • 19,422
  • 8
  • 58
  • 75
12

If you're having trouble with paths you can use

require Rails.root + 'db/migrate/20090408054532_add_foos.rb'
7

If you want to run it from console, this is what you are looking for:

$ rails console
irb(main)> require "#{Rails.root.to_s}/db/migrate/XXXXX_my_migration.rb"
irb(main)> AddFoo.migrate(:up)

I tried the other answers, but requiring without Rails.root didnt work for me.

Also, .migrate(:up) part forces the migration to rerun regardless if it has already run or not. This is useful for when you already ran a migration, have kinda undone it by messing around with the db and want a quick solution to have it up again.

Tasos Anesiadis
  • 1,000
  • 10
  • 33
6

Method 1 :

rake db:migrate:up VERSION=20080906120000

Method 2:

In Rails Console 1. Copy paste the migration class in console (say add_name_to_user.rb) 2. Then in console, type the following

Sharding.run_on_all_shards{AddNameToUser.up}

It is done!!

ramya
  • 281
  • 1
  • 4
  • 12
5

Please notice that instead of script/runner, you may have to use rails runner on new rails environments.

viniciusnz
  • 107
  • 1
  • 6
1

Looks like at least in the latest Rails release (5.2 at the time of writing) there is one more way of filtering the migrations being ran. One can pass a filter in a SCOPE environment variable which would be then used to select migration files.

Assuming you have two migration files 1_add_foos.rb and 2_add_foos.run_this_one.rb running

SCOPE=run_this_one rails db:migrate:up

will select and run only 2_add_foos.run_this_one.rb. Keep in mind that all migration files matching the scope will be ran.

szymek
  • 148
  • 1
  • 9