Run migrations from rails console
Asked Answered
E

9

86

Is there a way to run rake commands for db:migrate and db:rollback on the console?

It sucks to wait for the rails environment to load!

Edith answered 2/9, 2011 at 17:39 Comment(0)
Z
91

Rails <= 4

This will allow you to migrate without reloading the whole rails environment:

ActiveRecord::Migrator.migrate "db/migrate"

and rollback:

# 3 is the number of migrations to rollback, optional, defaults to 1
ActiveRecord::Migrator.rollback "db/migrate", 3

Rails >= 5 (thanks to @gssbzn, his answer is below)

Migrate :

ActiveRecord::MigrationContext.new("db/migrate").migrate

And rollback :

# 3 is the number of migrations to rollback, optional, defaults to 1
ActiveRecord::MigrationContext.new("db/migrate").rollback 3
Zilpah answered 2/9, 2011 at 17:49 Comment(9)
Note that if you're using Mongoid, it's the same: Mongoid::Migrator.migrate "db/migrate"Niles
This is perfect to add to your test_helper.rb in Rails appsGinter
Received error, bash: ActiveRecord::Migrator.migrate: command not found... using Rails 2.3.18, ruby 1.9.3p551, Now executed after executing the command inside the rails console.Aldarcie
In case for some weird reasons your migrations aren't located in 'db/migrate', use ActiveRecord::Tasks::DatabaseTasks.migrations_paths in its placeTapir
This is correct for Rails 4, but doesn't work for later versionsOiler
See @gssbzn's answer for compatibility with rails 5.2+Darla
Rollback for above 5 - ActiveRecord::MigrationContext.new("db/migrate").rollback - not mentioned but also worksSisera
This worked for Rails 5 using this command ActiveRecord::Migrator.migrate "db/migrate"Shelleyshellfire
For newer Rails versions, you also need to pass schema_migration: ActiveRecord::MigrationContext.new(ActiveRecord::Migrator.migrations_paths, ActiveRecord::Base.connection.schema_migration)Alopecia
C
125

In the console:

ActiveRecord::Migration.remove_column :table_name, :column_name

To update your schema.rb file after running migrations from the console, you must run rails db:migrate

Cubic answered 10/5, 2014 at 18:49 Comment(5)
@WestonGanger how?Dituri
@Dituri not sure that weston is correct here. I find that any time I run these commands, then I might have to do reload! to get the effect in the console, and having finished with the console, as long I exit the console, I do rails db:migrate, and it migrates them, and updates db/schema.rb . Really good to look at db/schema.rb . it shows all your tables. rails db:migrate updates schema.rb for you, at least I think that's what i've found.Helsell
@WestonGanger care to comment?(as your comment is under question)Helsell
@Helsell @nruth. The migration occurs as soon as this command is run and changes the database, the schema however will not be updated. Running rails db:migrate can automatically update the schema. However this is an extra step that is not in the answer.Ginter
@WestonGanger yeah but since you can do rails db:migrate, that's not manually updating the schema.rb file. That's automatically updating it.Helsell
Z
91

Rails <= 4

This will allow you to migrate without reloading the whole rails environment:

ActiveRecord::Migrator.migrate "db/migrate"

and rollback:

# 3 is the number of migrations to rollback, optional, defaults to 1
ActiveRecord::Migrator.rollback "db/migrate", 3

Rails >= 5 (thanks to @gssbzn, his answer is below)

Migrate :

ActiveRecord::MigrationContext.new("db/migrate").migrate

And rollback :

# 3 is the number of migrations to rollback, optional, defaults to 1
ActiveRecord::MigrationContext.new("db/migrate").rollback 3
Zilpah answered 2/9, 2011 at 17:49 Comment(9)
Note that if you're using Mongoid, it's the same: Mongoid::Migrator.migrate "db/migrate"Niles
This is perfect to add to your test_helper.rb in Rails appsGinter
Received error, bash: ActiveRecord::Migrator.migrate: command not found... using Rails 2.3.18, ruby 1.9.3p551, Now executed after executing the command inside the rails console.Aldarcie
In case for some weird reasons your migrations aren't located in 'db/migrate', use ActiveRecord::Tasks::DatabaseTasks.migrations_paths in its placeTapir
This is correct for Rails 4, but doesn't work for later versionsOiler
See @gssbzn's answer for compatibility with rails 5.2+Darla
Rollback for above 5 - ActiveRecord::MigrationContext.new("db/migrate").rollback - not mentioned but also worksSisera
This worked for Rails 5 using this command ActiveRecord::Migrator.migrate "db/migrate"Shelleyshellfire
For newer Rails versions, you also need to pass schema_migration: ActiveRecord::MigrationContext.new(ActiveRecord::Migrator.migrations_paths, ActiveRecord::Base.connection.schema_migration)Alopecia
D
32

Another way that I find neater to just run some migration command from console is this:

ActiveRecord::Schema.define do
  create_table :foo do |t|
    t.string  :bar
    t.timestamps
  end
end

This has the advantage that the contents inside the block is compatible with just copy and pasting random contents from a real migration file / schema.rb.

Drastic answered 18/3, 2015 at 3:15 Comment(1)
I've found this really helpful in diagnosing some db-specific issues with migrations. Thank you!Lanni
J
14

For rails 5.2 the accepted answer has been removed and replaced with

ActiveRecord::MigrationContext.new("db/migrate").migrate

Please be aware as this may also change for future versions of rails as they work to add multiple database connections

Joscelin answered 10/10, 2018 at 11:18 Comment(0)
O
14

For Rails 5 and Rails 6:

ActiveRecord::Base.connection.migration_context.migrate

For Rails 3 and Rails 4:

ActiveRecord::Migrator.migrate 'db/migrate'
Oiler answered 30/1, 2020 at 17:34 Comment(1)
This is the best answer for Rails 5 & 6, because it uses existing methods to get the migration context (instantiating it directly may not be reliable).Uta
S
7

I needed to pretend a migration was run to unblock a deploy, this can be done with:

class Mig < ActiveRecord::Base; self.table_name = 'schema_migrations';end
Mig.create! version: '20180611172637'
Sweetandsour answered 18/6, 2018 at 21:25 Comment(0)
U
5

You can use the %x[command]

%x[rake db:migrate]
Udelle answered 2/9, 2011 at 17:50 Comment(2)
That defeats the purpose to not have to wait for rails to load.Edith
@Edith yes agreed! That's why I think Benoit's answer is better :)Udelle
E
1

To run single migration

ActiveRecord::Migration.add_column(:table_name, :column_name, :data_type)

To run all migrations

ActiveRecord::Migrator.migrate('db/migrate')

To rollback n migrations

ActiveRecord::Migrator.rollback('db/migrate', n)

Exchequer answered 17/12, 2021 at 10:36 Comment(1)
Doesn't work with Rails 7. Use ActiveRecord::MigrationContext.new("db/migrate") insteadJohnsonian
F
0

I created a method in my .irbrc file that runs migrations then reloads the console:

def migrate
  if defined? Rails::Console # turn off info logging for Rails 3
    old_log_level = ActiveRecord::Base.logger.try(:sev_threshold)
    ActiveRecord::Base.logger.sev_threshold = Logger::WARN
  end
  reload! && migations_ran = true if ActiveRecord::Migrator.migrate(Rails.root.join("db/migrate")).any?
  ActiveRecord::Base.logger.sev_threshold = old_log_level if defined? old_log_level
  migations_ran ||= nil # useful exit status
end

See the entire file here: https://gist.github.com/imme5150/6548368

Folketing answered 13/9, 2013 at 9:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.