How do I manage the database/migration when checking out earlier commits - ruby-on-rails

Scenario description:
I have a master and a feature branch for my source control.
---- master
\-- feature
I have a column called useless_column for my User model, which is present in master branch, which i want to drop in feature branch.
Now, I drop useless_column using rails migrations in feature branch removing all code that depends on that column and commit. schema.rb and psql database are now updated.
Question:
Next, suddenly, I realize I made a mistake, and I want to go back to the master branch and discontinue working on feature branch. So, I git checkout -b master, but at this point I cannot db:rollback or schema:load or anything because the database has forgotten all the values in the useless_column which the master branch still depends on.
Does this mean I had to make a dump before I removed this column? If so, then the workflow is to make a database dump everytime you do a migration? If not, then how do you solve this problem?
Related link: How to work with Git branches and Rails migrations
Useful link: http://technotes.iangreenleaf.com/posts/2013-09-10-rails-migrations-and-schema.html

Related

I've overwritten a table in my database (locally), How can I stop this from deploying

I have a table named Impressions and recently (in a dev branch) I installed the impressionist gem which has overwritten this table.
My master branch is now showing the overwritten version and not my original. Fortunately, I haven't deployed, so I still have the data.
Other than exporting data from live, creating a new table and importing again.. is there a way I can fix this?
It's worth saying that my Schema on the master branch kept my old table columns, but when I renamed the table (in an effort to stop it being overwritten when I merge from the dev branch) the renamed table had the columns from the impressionist gem.
Why is this? I have schema checked in to my version control and so I feel uncomfortable knowing that the things I'm editing on my dev branches are having and effect on my master branch.
Rollback the database to one step by using the below command:
rake db:rollback STEP=1
& exceute the below command
rails d impressionist

schema.rb messed up due to migrations in other branches

Currently I'm working with a huge rails application and multiple branches with each a new feature for this application.
It happens a lot a feature will require migrations, which shouldn't be a problem until you merge it with master: schema.rb got updated with the information of your dev database!
To clarify:
1. Branch A has migration create_table_x
2. Branch B has migration create_table_y
3. Branch A adds another create_table_z and runs db:migrate
4. You want to merge Branch A with Master and you see table_x, table_y and table_z in the schema.rb of Branch A.
It's not an option to reset+seed the database before every migration in a branch or create a database per branch. Due to the huge size of 2 GB SQL data, it would not be workable.
My question:
Is it really required to keep schema.rb in the repository since it gets rebuilt every migration?
If so, is it possible to build schema off the migrations instead of database dump?
you should keep the schema within your repo. running the migration will fix merge conflicts within your schema.rb file for you.
my simple take on your questions
Is it Required? not really, but good practice.
"It's strongly recommended to check this file into your version
control system." -schema.rb
It is possible? yes but you may want to ask yourself if you really save any time by doing so, either manually or building the schema off your migrations elsewhere and pushing it in.
you ge tthe added benefit of using
rake db:schema:load
and
rake db:schema:dump
http://tbaggery.com/2010/10/24/reduce-your-rails-schema-conflicts.html
Keeping schema.rb in the repo is important, because you want a new developer (or your test environment) to be able to generate a new database just from schema.rb. When you have a lot of migrations, they may not all continue to run, especially if they rely on model classes that don't exist, or have changed, or have different validations in effect than when the migration was first run. When you run your tests, you want to dump and recreate your database from schema.rb, not by re-running all the migrations every time you run the full test suite.
If you're working on two different feature branches simultaneously, and changing the database structure in both, I think schema.rb is the least of your problems. If you rename or remove a column in branch B, branch A is going to break whenever it references the old column. If all they're doing is creating new tables, it's not as bad, but then you want schema.rb to be updated when you merge from master into A, so that A doesn't try to run the migration a second time and fail because the new table already exists.
If that doesn't answer your question, maybe you could explain your workflow a little more?
Fresh Temporary DB as a quick workaround
For example, do the following whenever you need pretty db/schema.rb on particular branch:
git checkout -- db/schema.rb
switch to the different development database, i.e. update config/database.yml
rake db:drop && rake db:setup
rake db:migrate
commit your pretty db/schema.rb
revert changes in config/database.yaml

git branch with migrations run

I checked out a branch in git to experiment with developing a feature that involved making three migrations, which I have run. Preserving the very small amount of data in the db is not important. How do I handle this when merging the branch back into master? Should I rollback the migrations before merging, and then run them again after merged (as seemed to be suggested by one SO answer), or do I leave it as is and just commit everything to the branch and then merge it without rolling anything back. Another SO answer suggested removing the db from the gitignore file, but it wasn't clear if that was only necessary in situations where preserving data might be important.
# Ignore the default SQLite database.
/db/*.sqlite3
You should not track your *.sqlite3 development files in git.
You should
Merge master into your branch
Make sure all is well
Checkout master
Merge the branch back into master
Continue development
The merge will pull in your migrations from the branch. You could rollback before the merge, do the merge, and then migrate, but there's no need; the resulting schema at the end will be identical.
In situations where a rollback/migration would be necessary, it's likely your migrations between master and the branch conflict with one another somehow. This is something you'd fix in step #2 above when you're "Making sure all is well".
As a general rule, you should be able to take a completely blank database, run rake db:migrate and end up with an up-to-date database structure without anything failing. This is why step #2 above is important, to ensure you're not merging a breaking/conflicting migration back into master.
As for situations where you are risking losing data in development, this is what fixtures are for. You can use Rails seeding functionality, or a gem like factory_girl.

Good Git deployment using branches strategy with Heroku?

What is a good deployment strategy to use with Git + Heroku (Ruby on Rails)?
Currently, the way I work with my origin Git repository: All features (or 'stories') are first checked out as branches, then get merged with master and pushed to origin.
Anything pushed to origin/master triggers a script that pulls the new rails code to the staging area (simple rails webserver).
When the time comes for me to push a new production version to Heroku, should I create a new branch (called something like production_version_121), and push that somehow to Heroku?
Ideally, I'd like to pick and choose which features from previous development versions I should include into the production branch... test it, and push to Heroku.
For example, I may not want all the latest code to get pushed to production. I might want to feature "a" that I had worked on and feature "c" both merged into production somehow, without including experimental feature "b" which needs more debugging.
N.B. I'm going to try avoiding Capistrano at first and get something working manually for now.
Any thoughts? Best practices?
In the Gemcutter project we simply have a production branch. Any changes that we want to see on the production site get merged into that branch, and then deployed with:
git push heroku production:master
The staging branch serves a similar purpose for the staging site (also on Heroku)
Ever since I read Vincent Driessen's A successful Git branching model, I have been hooked. My entire company (8 of us) have now standardized on this model and a few other places I've consulted with have also started using it as well.
Most everyone I've shown it to says they were doing something similar already and found it very easy to adapt.
In a nutshell, you have 2 branches that are permanent (master and develop). Most of the time you'll just be making branches off of develop and merging them back into develop. Things get a little more complex when you get into doing production releases and hotfixes, but after reading the post a couple of times, it becomes engrained.
There's even a command line tool called git-flow to help you out.
There are a variety of ways to go about this, and it really depends on your preference.
I'll give you one possible strategy off the top of my head: Given you already have an automated staging setup that uses master, I would suggest creating a 'production' branch. When you want to promote a fix/feature to production, you would just merge the topic branch into your 'production' branch.
git checkout production
git pull . my-topic-branch
(resolve any conflicts)
When you are ready to actually push that code to your production server, you should tag the branch using a unique name (probably with a timestamp). Then you simply push the production branch to Heroku.
git checkout production
git tag release-200910201249
I'd suggest creating a script or git alias to automate the tagging for timestamps, since using a consistent naming scheme is important. I use something like this:
git config alias.dtag '!git tag release-`date "+%Y%m%d%H%M"`'
That allows me to do just type git dtag when I want to tag a release with a timestamp.
You can view you tags using git tag and view them using git show release-1234. For more information on tags, run git help tag. You may also find this Github guide on tagging helpful. I'd also recommend reading up other people's workflows (here's a nice writeup) and pick and choose what works for you.

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