Rolling up Migrations? - ruby-on-rails

As I understand it the point of migrations is so you can revert the database back to a known state during the last stages of development.
Right now I'm still "fleshing" out my first Rails app and I'm wondering if its ok to roll up my migrations into bigger ones rather than dozens of changes.

The point of migrations is that you basically have a log of database changes, so then other developers can know what changes have been made, or to make sure your production environment gets the same changes you made during development.
As for your question: sure. If you create a new model, and then after a few minutes decide "this column could just be a string instead of text", roll back your migration, and change the column and then migrate again. No need to create a new migration.
Unless you've already committed the previous migration to source control that may have been fetched by other developers, or you've already applied the migration on the production server. Then you should use a new migration.

As an addendum to rspeicher, I limit the constraint to whether a migration has been released, not to whether it has been made available to other developers. If it's still pre-release, then the development team can be informed of any need to run migrations for any updates of the master code repository by using post-fetch hooks for the SCM being used. This is true of any configuration management change, not just migrations. For example, changing an implementation of something in the initializers folder may have no effect on a running instance of script/server in development mode. This is a ultimately a necessary mechanism for most teams in most technologies as well as for some configurations of continuous integration. Or, you need excellent communications channels in the team to make sure that everyone knows that a configuration change and restart is necessary.

Related

Entity Framework bug? "Context changed" Error, even when not

I have gotten myself into an odd Groundhog Day scenario with an MVC application of mine.
Unless I apply my workaround (Later in this question) each time I debug the application I'm presented with this error:
The model backing the 'UsersContext' context has changed since the
database was created. Consider using Code First Migrations to update
the database (http://go.microsoft.com/fwlink/?LinkId=238269).
I have not changed the model.
My workaround workflow is:
Add-Migration WHATEVERNAME (Makes a blank migration)
Delete this migration.
Run: Update-Database
Recompile & Run (Now without error)
Notes:
The __MigrationHistory hashes of the latest migration match in both script and in the database.
I have my MVC application & EF project as separate projects.
I have tried creating an -IgnoreChanges migration, to see if applying this would mitigate the issue. It did not.
This is quite frustrating, how would I solve this issue permanently?
Note: Automatic migrations are not suitable for my scenario.
Well, it's almost impossible to understand what's wrong without knowing much more detail. So all I can do is give you some clues of what you could try.
Stopping and restarting the app should not cause the DB to get out of date. Is it only when debugging? Have you tried running the app without debugging? Then recycle the app pool and running the app again.
Do you have any weird post-build step that will overwrite some DLL in your "bin" folder?
Is your app doing something that changes the database schema, thereby invalidating it when you next start up? Run SQL profiler to check what is happening to the DB when your app starts up.
Migrate back to the first version of your schema, and then back again (backup your DB first):
update-database -TargetMigration:0 -verbose
then
update-database -verbose
Temporarily comment out the bulk of your app to try to isolate the cause.
Create a brand new app with EF configured in the same way, copy the connection string and see if it happens for that. If not, then there must be something different. If yes, then show us your EF settings.
Hopefully something here that could give you an idea at least. Good luck!
Enabling migrations sets up the whole migration system. But to enable automatic migrations you have to include -EnableAutomaticMigrations which simply adds the line
AutomaticMigrationsEnabled = true;
into the newly generated Configurations.cs file.
In conjunction with the database initializer, development turnaround is more streamlined because you no longer have to type add-migration and update-database every time you make a change. That will happen automatically now. However, that’s not enough, if you want column removals you have to also perform step 3, where automatic data loss is supported.
When you are ready to release software (internally or externally) where you need strict version control and to upgrade databases on site, you should remove automatic migrations and add a manual migration point.
This can happen when updating to EF6 which made schema changes to the _MigrationHistory table (https://msdn.microsoft.com/en-us/data/jj591621)
The EF6 version has a new column ContextKey so the migration is probably trying to add that column.
I'm guessing if you scaffold it will just be making those changes - or perhaps there's something you changed a long time ago that wasn't 'picked up' yet for some reason.
OR if you just don't want to deal with it right now you can disable migrations temporarily.
System.Data.Entity.Database.SetInitializer<UsersContext>(null);

Ruby on Rails Database Deployment with Gerrit

I'm considering using Ruby on Rails for my next project. Understanding the deployment of a rails website is easy enough to understand (sounds like I'll be using Phusion Passenger)
But now I'm trying to figure out the database. I see a lot about "database migrations", which allow me to update the database using ruby code. I also see that I'm allowed to create both an up and down variant of these migrations.
However, I can only fathom how this works cleanly in a single direction. Imagine if I suddenly say "The color column cannot be null". So, the up will make it required and give all NULL entries a default value. But what will the down do? If you care about it being identical to how it started, you can't just set the default values back to NULL.
This doesn't really matter much for releases to production. That will likely just be done in a single direction (in the up direction). However, I want to use Gerrit for code reviews as well as setting up a bot to run a build before allowing check-ins...
So how could that work? From one code review to the next, the build server will check out the new set of code, and run the migrations? But when this happens, it won't even retain the migration code from before, so how could it run the down steps? As an simpler example, I do not see how I could check out an old version of the code and "db migrate" backwards.
Yes, you can't check out an old version of the code and then run a down migration from a newer version of the code. You would need to run the down migration before rolling back to the older code.
There are many, many cases where a down migration is just not practical or possible. That's not necessarily a bad thing. It just means that you have defined a 'point of no return', where you won't be able to restore your database to an earlier state.
Migrations like creating a table or adding a column are easily reversed by simply destroying that table or removing that column. However, if you are doing something more complex, such as adding default values or moving data around, then you can tell Rails that it's not possible to reverse this migration:
def down
raise ActiveRecord::IrreversibleMigration
end
I would recommend that Gerrit should never assume anything about the database. It should start with a fresh database each time a new version is deployed, and run db:migrate to run all your migrations. You can use gems like factory_girl to populate your app with demo data for testing purposes.

Is there a good migration management/clean-up strategy after completing a Rails project?

As I go through the development of an application, in my development environment, I make mistakes and create tables that need to be modified later - as I use the app and see the folly of earlier design decisions.
But when I push to production, I don't want to replicate all those changes when I can just create the 'perfect' table in one migration.
Is there a strategy or something I can use that can help me do that?
If this is the initial push to production, you should be able to copy your schema.rb contents (which should reflect the schema after all migrations were applied) into one giant migration file, and remove all previous migration files.
If your production environment has already been created and the database has been migrated up to a point, then you'll need to use something more intelligent that can bridge the gap between the current state and the latest schema. Unfortunately, I'm not aware of any such project at this time.

What are the dangers of using EF Migrations (or any auto-migration framework) in production?

I'm considering using Entity Framework 4.3 migrations in a production site. The following is my concern:
If the migration fails for whatever reason, I want all statements
rolled back and the site placed in a down state so no users can use
the site while I try to fix the problem. The only thing is I can't
fall back to executing the scripts by hand against the database since
migration files are compiled in the assembly. I could keep track of
both migration files and sql script files separately but at that point why use
migrations at all.
At work, script files are stored in a SQL folder (that no one can browse to) on the site. Previously run script files are registered in the database. When new script files appear in the folder (and aren't in the database), if a user is an admin, they'll be redirected to a DB portal, else get a site-down-for-maintenance. If we try and fail to execute any scripts from the portal, we grab the new scripts and try to run them manual inside of express studio. This has worked for over a decade. I'm only exploring migrations to see if a better way has arrived. It doesn't feel like it. Please let me know if there's a better way and if it's not Migrations, what is it.
I would definitely not use automatic migrations in a production environment. In fact, I'm too much of a control freak to use automatic migrations at all. I prefer code based migrations to ensure that all databases (developers' own personal, test environment, production) have gone through exactly the same update sequence.
Using code-based migrations where each migration step gets a name, a separate migration script can be generated for use when lifting test and prod environments. Preferably it should be run on a copy of the database to validate before running on the real prod environment.
Added Later
To prevent EF Migrations from doing anything automatic at all, a custom initializer strategy can be used. See my blog or the Deploying EF Code First Apps to Production Database Stack Overflow question.

Managing Rails Migrations for different branches on the same machine

I'm a one-man-band at the company I work for. I develop a Rails application for internal use within the company. Since the beginning of the project I have used SVN for source control and done most, but not all, development in trunk. Occasionally, when I have had very significant changes to make, I have branched and made the changes merging back in when done. All very typical.
However, none of those "significant changes" that I have had to make have ever touched the database migrations. They have always been view/controller stuff.
In this situation, with one development box, how do I play around with migrations and various database changes that I may or may not keep? I don't want to have to remember to revert all the migrations back to the beginning of the branch before I throw the branch out if it doesn't work.
I have considered setting up special development environments and databases (app_branch instead of app_development) but that seems to work strongly against the notion of "easy branching" that experimental development tends to rely on.
Are there best practices for this situation? What are others out there doing in this situation?
I try hard to keep my development database "droppable." If I lose it all - no big deal. My migrations are ready to build it up again from scratch and there's always a script with seed / test data in it somewhere. I guess it's not especially clever.
If I needed a new branch for database work, I would just check it out, drop, create, rake, and then seed. I guess I'd write a script to get it done because when I go to adandon the branch, I'm going to have to go through the same process again from the trunk.
Make sure your schema.rb file is in version control. That way, as you switch branches, you can drop your DB and then do rake db:schema:load as necessary.
Also, you really should switch to Git. It will make branch management a lot easier than SVN. (I speak from lots of experience with both programs.)
Well, if you want to have different schemas, you'll need multiple databases. "Easy branching" refers to source control, typically, and not databases. As far as I know there's no easy way to branch databases like you would branch in, say, git.
One thing we do to manage our dev/production branches is we check our current git branch in our database.yml file. If the current branch is production, we use one database, otherwise we use our dev database. something along the lines of this:
<% if 'git branch' =~ /^\* production/
db = 'production_database'
else
db = 'development_database
end %>
development:
database: <% db %>
Note, the 'production_database' refers to a local version of the production schema, not the live production database.
I wrote a script for dealing with this exact problem. It is based around git, but you could easily change it to work for svn:
https://gist.github.com/4076864
Given a branch name it will:
Roll back any migrations on your current branch which do not exist on the given branch
Discard any changes to the db/schema.rb file
Check out the given branch
Run any new migrations existing in the given branch
Update your test database
I find myself manually doing this all the time on our project, so I thought it'd be nice to automate the process.
If I am creating a branch where you are making siginificant changes, you can create a copy of the database before creating your migrations then change the development section of database.yml inside the branch. Leave your :production section alone and then decide which version of the database you want to keep for future development when you merge the branch back into the trunk.
We do this with feature releases. I'll have local DBs for version 1, 2, 3 like "db_v1", db_v2", etc. As we roll through the versions, each subsequent development branch gets an edit in database.yml while the trunk stays on the last version for bug fixing.

Resources