Can I delete a migration file? - ruby-on-rails

When I ran bundle exec rake db:test:prepare I got the following:
rake aborted!
Multiple migrations have the name CreateMicroposts
To check the status of my migration files, I ran
rake db:migrate:status
And got:
Status Migration ID Migration Name
------- --------------- -----------------
up 20120616205407 Create users
up 20120622103932 Add index to users email
up 20120622114559 Add password digest to users
up 20120628095820 Add remember token to users
up 20120704123654 Add admin to users
down 20120706103254 Create microposts
up 20120707073410 Create microposts
As you can see, I have two migration files with the exact same names and the exact same code in them. It's only their statuses differ, i.e. Up and Down.
What does Up and Down signify?
And which one can I delete, if I have to?

The problem is that you have two different migration files containing the header
class CreateMicroposts< ActiveRecord::Migration
rake db:migrate:status does not check the status of your migration files. It tells you what migrations will be applied if you run rake db:migrate. The up/down labels are pretty much self-explanatory: it tells you whether the migration will be applied via the up method or the down method. The up method is ran when you migrate and the down when you rollback a migration. You can make some further reading about Rails migrations here.

up is the method called when "evolving" (ie migrating to a new schema), while down is the method called when "regressing" (ie migrating to an older schema version, because one of your changes doesn't suit you). db:migrate calls up, db:rollback calls down. In recent versions of rails, there's change that handles both at the same time.
As for the deletion... I don't do activerecord much these days, but I think you're free to do whatever you want with your files. I don't think deleting a duplicate file will do any harm, and if it does.. Well, you use source control, right ? :)

Related

ActiveRecord how to ignore pending migrations

The problem is the following:
I have db/seed.rb full of initial data.
One of migrations depends on data this seed provides.
I'm trying to deploy my app from empty db.
Result is:
RAILS_ENV=production rake db:migrate - fails due to lack of initial data
RAILS_ENV=production rake db:seed - fails due to pending migrations
I wanted to somehow tell rake to ignore pending migrations, but unable to do it so far.
UPDATE (due to additional experience)
Sometimes migrations and model code goes out of sync, so migrations are not being run.
To avoid this problem recently used redefining of model in migrations:
# reset all callbacks, hooks, etc for this model
class MyAwesomeModel < ActiveRecord::Base
end
class DoSomethingCool < ActiveRecord::Migration
def change
...
end
end
I am not very sure if this will help you. But I was looking for something and found this question. So it looks like this might help:
In RAILS_ROOT/config/environments/development.rb
Set the following setting to false:
# NOTE: original version is `:page_load`
config.active_record.migration_error = false
In my situation it now does not show the pending migration error anymore. Should work for rake tasks and console for the same environment as well.
Source in rails/rails
Rename the migration dependent on the data from:
20140730091353_migration_name.rb
to
.20140730091353_migration_name.rb
(add a dot at the start of the filename)
Then run rake db:seed (it will no longer complain on the pending migrations) and then rename back the migration.
If you have more migrations following after, you have to rename all of them or just move it temporary away.
Rails stores migration information in a table called schema_migrations.
You can add the version from your migration into that table to skip a specific migration.
The version is the number string which comes before the description in the file name.
[version]_Create_Awesome.rb
I had a similar issue. I commented out the add_column lines and ran the rake db:migrate commands and then removed the comment when I will need it for the testing or production environment.
There is no way unless you monkey patch the Rails code. I strongly advise you to fix your migrations instead.
A migration should not depend on the existence of some data in the database. It can depend on a previous migration, but of course absolutely not on the data on the db.
If you came across the "pending migrations" issue when trying to seed your data from within a running Rails application, you can simply call this directly which avoids the abort_if_pending_migrations check:
ActiveRecord::Tasks::DatabaseTasks.load_seed
See where seeds are actually called from within ActiveRecord:
https://github.com/rails/rails/blob/v6.0.3.2/activerecord/lib/active_record/railties/databases.rake#L331
and see the DatabaseTasks docs:
https://apidock.com/rails/v6.0.0/ActiveRecord/Tasks/DatabaseTasks
https://apidock.com/rails/v6.0.0/ActiveRecord/Tasks/DatabaseTasks/load_seed

How to keep overview of the migrations?

I have a question regarding my migrations in rails.
Normally when i want to add a colum to a model for i dont make extra migrations but instead i perform this steps:
rake db:rollback
next i change the migration file in db/migrations and rerune:
rake db:migrate
The biggest problem is that when i do this i loose my data.
Previous i wrote migrations from the command line with for example
rake g migration Add_Column_House_to_Users house:string
The problem with this approach is that my db/migrations folder afterwards get very large and not very clear! I mean at the end i dont know wich variables the object has! Im not an expert in rails and would like to ask you how to keep the overview over the migrations!Thanks
Just a minor thought - I just use the file db/migrate/schema.rb to determine whats in the database as opposed to tracking through the migrations
You definitely shouldn't use db:rollback with a table with existing data.
I have a few production RonR apps with a ton of data and there are 100+ entries in the migrations table and adding new migrations to tweak tables is the rails way to do things. Not sure what you mean by lucid, but your schema and data model are going to change over time and that is ok and expected.
One tip. The migrations are great, but they are just the beginning, you can include complex logic as needed to fix your existing data (like so)
Changing data in existing table:
def up
add_column :rsvps, :column_name_id, :integer
update_data
end
def update_data
rsvps = Rsvp.where("other_column is not null")
rsvps.each do |rsvp|
invite = Blah.find(rsvp.example_id)
...
rsvp.save
end
end
Another tip: backup your production database often (should do this anyway), but use it to test all of your migrations before deploying. I run scripts like this all the time for local testing:
mysql -u root -ppassword
drop database mydatabase_dev;
create database mydatabase_dev;
use mydatabase_dev;
source /var/www/bak/mydatabase_backup_2013-10-04-16.28.06.sql
exit
rake db:migrate

Rake task to list all migrations for a given model

On the terminal, is there a rake task to list all the migrations which have been run on a particular model? If not, how do I go about building one?
When I ran rake -T, rake db:migrate:status seemed to be the right answer, but it gave me Migration Name as one of the columns. And though the name Add logo to company does indicate Company model, not all migrations have such explicit names. Case in point being Change data type for content. I have 400 odd migration files, so this feature would be really helpful.
So, the ideal output would be:
database: abcd_development
Status Migration ID Migration Name Model Name
----------------------------------------------------------
Thanks!
If you've been sticking with the migration naming conventions, you could just pass the output of rake db:migrate:status through grep:
rake db:migrate:status | grep 'compan'
This isn't perfect, though - migration names aren't required to have anything to do with what they actually do - a migration might add the column 'name' to the 'companies' table and be named EvacuateWeaselTubes and still run just fine.
If you wanted to build a task that could overcome this problem, it would have to parse each of the migration files to see what it changed. Since there's many ways to specify a change in a migration (add_column, a create_table block, or calling execute('CREATE whatever'), for instance), you'd probably want to search for mentions of Model.table_name, then check the schema_migrations table to see if it had been run.

Destroying an invalid migration

New to Rails here. Couple of questions about migrations:
I created a migration that I no longer want. I want to remove it. Is the correct command simply rails destroy migration AddMyColumnToMyModel ?
Let's say I mistype that migration name that I want to destroy... Here's what happens when I attempt to destroy a migration that does not exist.
$ rails destroy migration Blah
invoke active_record
remove migration.rb
It says it's removing migration.rb... Is this a bad thing?
Sure, that's the right command. Just be careful: if you actually ran the unwanted migration by using rake db:migrate to commit the changes to your database, be sure to run this before anything else:
rake db:rollback
What that does is run the down method on your latest migration. It does absolutely the same thing as:
rake db:migrate:down VERSION=20130529014413
Where the version number corresponds to that of your latest migration. It can also take a STEP parameter in case you need to roll back a bunch of migrations instead of only one, like so:
rake db:rollback STEP=3
Of course, if you just generated your unwanted migration and never ran it, there's no need to roll anything back. You can use the command you posted or manually delete the corresponding file to get rid of it.
Source: http://guides.rubyonrails.org/migrations.html#rolling-back
Don't worry, that's not doing anything to your code.

My Migration broke after renaming a model, I can no longer run a db:create

here's what happened. I used to have a Model called Message, I then wanted to rename it so I created a migration that renamed that table from Message to Thread. I had later migrations that then added to that table.
That worked fine, it terms of db:migrate to move forward with our existing databases. Now I noticed that when I do a db:create to create a fresh db it fails, as rails creates Message, then when it goes to add a field to message I get a:
uninitialized constant AddActiveMessageIdToWalls::Message
I think the problem is that I also renamed all the controller & models from message to thread and now the migration can't find the model when migrating? Does that sound right?
How do you deal with this in the rails world? Thanks
I like to keep my db/schema.rb updated to avoid this. So when I need to create the db in a new environment, I just need to do the rake db:create and rake db:schema:load. No migration is needed.
easiest solution: just add an empty Message < ActiveRecord::Base subclass in the earlier migration.
... migration file ...
class Message < ActiveRecord::Base;end

Resources