Schema Migrations Table
Asked Answered
B

8

59

In my Rails 4 app I would like to collapse my migration files into one large file (similar to schema.rb) as it's time to do some housekeeping but I'm not sure on how to access the table in the database that stores migration data so that when I run a migration I don't receive any errors/conflicts.

Question How can I access and delete the data in the table that stores migration data?

Bolanger answered 30/9, 2013 at 17:33 Comment(6)
Have you tried copy/pasting the schema.rb file into a migration file?Discourage
I don't have a problem creating the single migration file - but if I just change the migration files without considering the db I will get errors during a migration.Bolanger
My current understanding is that you wish to have a file that stores all your migrations, so that you can clean em up? If so, I'd suggest looping through them and writing the data to a new file. Using methods like File .glob etc...Discourage
No - You are misunderstanding. Please see the questionBolanger
ok somehow I didn't get your questionDiscourage
a more popular similar question here - https://mcmap.net/q/330783/-rebase-rails-migrations-in-a-long-running-project/753705Countess
I
83

see this answer for Rails 4+ (TL;DR: use ActiveRecord::SchemaMigration)

original answer from 2015 for Rails 3 (I'm a fossil, been on Rails since <1.0 😆)

for fun, you can also manipulate these in the console by making a model class for them...

class SchemaMigration < ActiveRecord::Base; self.primary_key = :version; end

then you can do SchemaMigration.all, SchemaMigration.last.delete, etc.

Really just a substitute for using SQL, and it is very rare that you would need to mess around at this low level… generally a bad idea but cool to see how to do it :)

Innerve answered 11/2, 2015 at 4:51 Comment(3)
This works - just run that code in Rails console to create a model in that console-instance. Then you can select rows from that table with .where(:version => ...) and delete references to migrations as needed. Very helpful since PGAdmin won't let you delete rows from tables that don't have a primary key specified with the gui.Lap
'generally'. But there are edge cases. Created a migration with a reference, adding default: 1 where 1 did not exist. The migration halted... but the database was already altered. Said migration could not run. This saved the day and sanity cycles for me. Needless to say, this requires monkish patience and scrutiny before altering...Mccarver
@Lap you can alter the schema_migrations table with psql commands. see answer below.Mccarver
B
64

Another solution could be to access it through:

ActiveRecord::SchemaMigration

The answer given by David didn't work in my context.

Birdie answered 6/4, 2016 at 12:47 Comment(3)
This is so much cleaner than the defining a new model, it should really be the top answer.Uncinus
I don't believe this is available in Rails 3.2, but it is the best solution for 4+.Shelve
This answer is much better anywayBurkett
F
21

The schema_migrations table holds the revision numbers; with the last record being the most recently executed migration. You can just manipulate these records manually.

Futhark answered 30/9, 2013 at 18:4 Comment(6)
Thanks - my question is how can I access this table - do I use the console? I want to delete all the records and then create a new migration - this sound ok?Bolanger
If this does not need to be repeatable (i.e. none of this is in production yet), I would just use your db shell (psql or mysql, etc) and run a SQL query.Futhark
it's psql but never used the shell beforeBolanger
If you have a postgres role login as sudo -u postgres psqlFuthark
Then run whatever update or delete statement you want to run.Futhark
Mark this as the answer, if you actually used this information to solve your issue.Futhark
M
11

to get the last version:

ActiveRecord::SchemaMigration.last.version

or all versions:

ActiveRecord::SchemaMigration.all.map(&:version)
Mcalpine answered 26/4, 2019 at 14:24 Comment(0)
L
7

Not sure why you want to do this but here you go:

ActiveRecord::Migrator.get_all_versions

Lagunas answered 19/1, 2017 at 5:46 Comment(0)
L
1

For Rails 7.1+ use

ActiveRecord::Base.connection.schema_migration.table_name

See more at: https://github.com/rails/rails/pull/45908 and the final changelog at https://github.com/rails/rails/releases/tag/v7.1.0

Move ActiveRecord::InternalMetadata to an independent object.

ActiveRecord::InternalMetadata no longer inherits from ActiveRecord::Base and is now an independent object that should be instantiated with a connection. This class is private and should not be used by applications directly. If you want to interact with the schema migrations table, please access it on the connection directly, for example: ActiveRecord::Base.connection.schema_migration.

Eileen M. Uchitelle

Librettist answered 28/2 at 0:52 Comment(1)
This should now be the accepted answer. It's worth noting while its an independent class, it has some methods which I found useful such as: .count, .versions, delete_version, create_version. Read more: rubydoc.info/docs/rails/ActiveRecord/…Hickory
F
0

As of Rails 7.1.3, this is no longer possible as ActiveRecord::SchemaMigration No longer inherits from

ActiveRecord::Model

As a workaround, you can just define a temporary model in your code:

class TemporarySchemaMigration < ActiveRecord::Base
  self.table_name = 'schema_migrations'
  self.primary_key = 'version'
end

https://github.com/rails/rails/commit/436277da885

Frediafredie answered 23/2 at 6:58 Comment(0)
M
-1

I've had to do some cleanup of the sort: accumulation of seemingly trivial migrations create such pollution that things stop making sense.

As a last phase of development (not recommended once in production), you can clear out the schema_migrations table, consolidate your migrations (one-to-one with classes) and create a new table (beware: running migrate has different behaviours, depending on mysql vs postgresql)

@david-lowenfels answer is perfect for this context.

All this, naturally, assumes you haven't made errors in keys, indices, defaults. This is a serious task, but not an insensible one at the end of a development phase.

Mccarver answered 31/8, 2020 at 11:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.