Saas 3.10- Databases And Migrations: Difference between revisions

From Expertiza_Wiki
Jump to navigation Jump to search
No edit summary
No edit summary
 
(26 intermediate revisions by the same user not shown)
Line 1: Line 1:
'''Saas 3.10 - Databases And Migartions'''
'''Saas 3.10 - Databases And Migrations'''
<p>A Database<ref>http://en.wikipedia.org/wiki/Database</ref> is a coherent collection of data with inherent meaning. Random assortment of data is not a database. Data is organized in order to model relevant aspects of reality, so that it supports processes requiring this data.
<p>A Database<ref>http://en.wikipedia.org/wiki/Database</ref> is a coherent collection of data with inherent meaning. Random assortment of data is not a database. Data is organized in order to model relevant aspects of reality, so that it supports processes requiring this data.
Data Migration is related to transfer of data between storage types, formats, or computer systems. This is performed programmatically to accomplish an automated migration so that humans are free from doing this repetitive task.
Data Migration is related to transfer of data between storage types, formats, or computer systems. This is performed programmatically to accomplish an automated migration so that humans are free from doing this repetitive task.
</p>
</p>


== Database ==
<p>
A Database is nothing more than a collection of meaningful information.  Databases can be of multiple types, for example Distributed Databases, Relational Databases, Flat File Databases.  A database could be as simple as a text file with a list of names or it can even be very complex as a large relational database management system.<br />
Examples:
<ol>
<li>Banking Systems where accounts are maintained and it is made sure that money does not disappear as a result of system failure.</li>
<li>Airline Reservation Systems where the plane details, the airport details and the customer details are maintained.</li>
<li>Hotel Management Systems where the availability of rooms, the rates and the customer details are maintained.</li>
</ol>
</p>


== Database Migration ==
<p>
Every application in reality has a database in the back end to store all the relevant data of the application. We should not test the application on database because it may contain valuable data like customer information in a banking system. So editing that data present in the database is not a good idea. The solution Rails<ref>http://guides.rubyonrails.org/getting_started.html</ref> provides for above problem is Defining three different environments: Development, Production and Testing each of which has a separate database and appropriate database types.</p><p>
The Development Environment is what we use while developing the application. The production environment refers to the database that is used when the application is published in the real world. The testing environment is meant for testing tools.  Testing of the application is done using Testing tools which automates the entire testing procedure. Since there are different databases in each environment, the problem that occurs is changes made in one Database do not reflect in the other.</p><p>
A programmer is also responsible to tell the other developers what changes have been made in the database. Also one has to keep track of which changes need to be run against production machines during deployment. The solution for the above problem that rails offers is data migration. Databases of different types can also be migrated between the three different environments. For example, we may use  SQLlite<ref>http://en.wikipedia.org/wiki/SQLite</ref> in Development environment, but we can still migrate into production environment where heroku<ref>http://en.wikipedia.org/wiki/Heroku</ref> may have been used. The source is portable and the back end understands what operations to do on the database.</p><p>


In reality Rails migrations are similar to version control of databases. Rails migrations is actually used since databases change requires modifications to both code and data. Hence we cannot use a source code version control system like Subversion<ref>http://betterexplained.com/articles/a-visual-guide-to-version-control/</ref> or Sourcesafe<ref>https://wiki.library.ucsf.edu/display/~128507@ucsf.edu/Source+Safe+vs.+Subversion</ref>. 


== Overview ==
</p>


OO languages can be either general purpose like C++, Java and Ruby, or domain specific, like Jquery and Kiddo. The following example shows how the two kinds of languages would work if used in the real world.
== Creating A Migration ==
<p> 
A migration is a sub class of ActiveRecord:: Migration which implements two methods: ‘up’ and ‘down’. The “up” method performs the required changes or transformations while the down methods reverses or roll backs them.</p><p>
A migration can be created using the following command:
<pre>
rake generate migration CreateCourse
</pre>
Migration Created :
<pre>
class CreateCourse < ActiveRecord::Migration
def up
create_table :course do |t|
  t.string :name
  t.text :description
  t.timestamps
end
end
def down
drop_table :course
end
end
</pre>
The above migration CreateCourse has just been created, but has not been applied to the Database yet. This migration will add a table called courses with string column called name and the text column called description. A primary key column called id will also be created by default. The time stamp columns created_at and updated_at which ActiveRecord populates automatically will also be added. Reversing this migration is nothing but dropping the table.</p>
<p>
Migrations can also be used to fix bad data in the database or generate new fields.</p><p>
For Example:
<pre>
class AddGradesToStudents < ActiveRecord::Migration
def up
change_table :students do |t|
  t.boolean :receive_grade, :default => false
end
User.update_all ["receive_grade = ?", true]
end
def down
remove_column :students, :receive_grade
end
end
</pre>
The above migration adds receive_grades to the students table. We want the default value to be false for new students. But existing students are considered to have a grade, So we use the student model to set the flag to true for existing students.</p><p>


ActiveRecord<ref>http://api.rubyonrails.org/classes/ActiveRecord/Base.html</ref> provides methods that perform common data definition tasks in a database. A migration is like a Ruby class so you’re not limited to these functions. For example, after adding a column you can write a code to set the value of that column for existing records (if necessary using your models).  The kind of object that  is yielded as a result of the migration code is object representing table.</p>
         
== Updating Migrations ==
<p>
If you wish to make changes to the migration and you have already run the migration then you cannot just edit the migration and run it again. Rails will consider it has already run the migration, so it will do nothing on running “rake db:migrate”. The migration has to be rolled back and then make changes to the migration and run it.
It is not recommended to edit existing migration and that too if it has been run on production systems. Instead, writing a new migration that performs the changes required is better. Making changes to a newly generated migration that has not been committed to source code is relatively safe.</p><p>
Migrations are stored as files in the db/migrate directory, for every migration class. The name of the file is of the form YYYYMMDDHHMMSS_create_course.rb, that is nothing but a UTC timestamp identifying the migration followed by an underscore followed by the name of the migration.
</p>


'''The General Purpose Programming way of ordering hash browns at Waffle House'''<ref>Building DSLs [http://www.code-magazine.com/article.aspx?quickid=0902041&page=1]</ref>
== Anatomy of Migrations ==
<p>
Migrations are a subclass of the Rails class ActiveRecord::Migration. The class must contain at least two methods i.e up and down.
<pre>
class CreateCourses < ActiveRecord::Migration
def self.up
#...
end
def self.down
#...
end
end
</pre>
The ‘up’ method used to apply schema changes for this migration and the ‘down’ method is used to undo the changes. Example: the ‘up’ method creates a table with all the attribute description for the migration whereas the ‘down’ method can be used to drop the table for the same migration.
<pre>
Class CreateCourses < ActiveRecord::Migration
def self.up
      add_column :room_no, :integer
end
def self.down
      remove_column :room_no
end
end
</pre>
</p>


Harvest the potato, wash it, and chop it into little pieces. Put the pieces in a pan with oil and fry till they turn golden brown, and then drain the oil away and put them on a plate. Now cut some jalapeno peppers and spread on the potatoes. Then add cheese, which you can get by milking a cow and.....  
== Relationship between Model and Migration ==
In Rails, a model internally maps itself to a database table. The table in the database must be the plural form of the model’s class. If we generate a model called Course, Rails automatically looks for a table called courses in the database.
You can use the Rails generator to generate both the model and a corresponding migration using the following commands:
<pre>
rake generate model Course name: string description: text
</pre>
will create a migration that looks like this
<pre>
class CreateCourses < ActiveRecord::Migration
def change
  create_table :courses do |t|
t.string :name
t.text :description
t.timestamps
  end
end
end
</pre>


== Creating a Standalone Migration ==
If you are creating migrations for other purposes, then a migration generator is used:
<pre>
$ rails generate migration AddSemesterToCourse
</pre>
This will create an empty but appropriately named migration:
<pre>
class AddPartNumberToProducts < ActiveRecord::Migration
def change
end
end
</pre>


'''The OODSL way of ordering hash browns at Waffle House'''
== Applying Migration to Development ==
<p>
Since CreateCourse migration has been created but not applied to the database, the following command is used to apply the migration to the development database:
<pre>
rake  db:migrate
</pre>
Every Rails Database has a table called schema_migrations maintained by the migration code. Whenever a migration is applied successfully a new row will be added to schema_migrations table. The schema_migrations table has a version column. When you run rake db:migrate, the task first looks for the schema_migrations table. It will be created if it does not exist. The migration code then looks at all the migration files in db/migrate and skips from considering any that have a version number that is already in the database. It then continues by applying the remaining migrations in turn creating a new row in the schema_migrations table for every migration.
</p>


I would like it Scattered, Smothered, and Peppered please. Thanks!
== Applying Migration to Production ==
<p>
The following command is used to apply migration to the production database:
<pre>
heroku rake db:migrate
</pre>
In the above example the production database is Heroku.
</p>


== Running Specific Migrations ==
<p>
If you need to run a specific migration up or down, the db:migrate:up and db:migrate:downtasks will do that on including the version also. 
</p>
For example,
<pre>
rake db:migrate:up VERSION=20080906120000
</pre><p>
The above command will run the up method from the 20080906120000 migration. These tasks still check whether the migration has already run, so for example db:migrate:up VERSION=20080906120000 will do nothing if Active Record believes that 20080906120000 has already been run.
</p>


For a person who works at Waffle House, or goes there regularly to eat, it is a no brainer that the second method is much more efficient. OODSLs take advantage of the context within which communication takes place. By using implicitly understood jargon, the task at hand can be accomplished in a way that is easier to comprehend for a specialized type of user.
== Rolling Back a Migration ==
 
<p>
 
The following command is used to rollback the last migration:
OODSLs can be of 2 types:
<pre>
 
rake db:rollback
* Internal
</pre>
* External
Rollback is performed when you made some mistake and instead of tracking down the version number of the previous migration, you can just rollback and run it after making changes.</p><p>
 
If you need to rollback several migrations, a STEP parameter is used. For example,
 
<pre>
Internal OODSLs are languages that are built on top of existing languages. An internal OODSL makes use of the host language syntax to provide the feel of a domain specific language. It is not universally defined as to when a language/library becomes an OODSL. JQuery is one such example. It is a JavaScript library, which offers an easy way to perform functions like element selection. It can also be argued that JavaScript itself is a domain specific language.
rake db:rollback STEP=2
 
</pre>
External OODSLs are those that are built from scratch. With the current technology, it is far more easy to churn out several internal OODSLs than to build one from scratch. External OODSLs have their own syntax, as well as their own methods of compilation/interpretation.
The above command will rollback the last 2 migrations.
 
The db:migrate:redo task is an easy way for doing a rollback and then migrating again. If you need to redo several migrations, a STEP parameter is used. For example, in order to redo the last 4 migrations, the command is
== History ==
<pre>
OODSLs cannot be spoken about without first a brief introduction to Domain Specific Languages and the Object-Oriented programming paradigm.  
rake db:migrate:redo STEP=4
 
</pre>
In a nutshell, DSL<ref>DSL examples[http://www.semanticdesigns.com/products/DMS/DomainSpecificLanguage.html]</ref> is a language that is specific to a particular domain. DSLs are different from general purpose programming languages like C++ and Java. They take advantage of the fact that there are groups of users who rather than communicating every single thing, are able to implicitly understand certain terms and notations. This makes communication much more efficient for such a group. Eg: 2 basketball fans will talk in basketball jargon. Not everyone will understand what zone defence, 3 pointers and jump ball mean. The jargon serves the specific purpose of easing communication between 2 basketball fans. Some would argue that DSLs have been around for a far longer time dating back to even before the advent of computers. Subway maps, electronics circuit diagrams all demonstrate properties of a DSL. Since then, DSLs have come a long way. Domain Specific Languages (DSLs), as they are spoken about now, have been around since the 1970's and their origin can be traced back to a tool called Draco. Since Draco, computers have made it possible to design a whole host of other useful DSLs. Some of the more popular ones among them are SQL, Prolog, Verilog, HTML etc.
“rake db:reset” is the command for resetting the database. This will drop the databse, recreate it and loads the current schema into it.
 
</p>
Object-Oriented Programming (OO) is a programming paradigm that tries to apply real world principles to make programming easier. OO has been around since the 1950's. Starting with Simula and Smalltalk, OO languages have come a long way since then, and has grown to become one of the most popular programming paradigms employed worldwide. Some of the modern object oriented languages include static languages like C++, Java, C#, and dynamic languages like Perl, Ruby etc.


OODSLs, that bring out the features of both DSLs as well as OO languages are a fairly recent invention. OODSLs have been around since the 1980's/1990's. They are now primarily used in the realm of web development, game development, and are also used in certain specialized industries like music.
== Problems with Migration ==
 
<p>
== Examples ==
One major problem Migrations suffer is that most databases do not support the rolling back of create table or alter table i.e. DDL statements in general. Let’s consider an example where a migration tries to create two tables.
=== PHP ===
[http://en.wikipedia.org/wiki/PHP<code>PHP</code>] is an OODSL that is commonly used for web development. It is an open source web development framework that is designed to make web development simpler and easier. The language can be perceived as a general purpose language, but it also has domain specific components designed for the web domain alone. PHP is in general embedded into HTML to perform server side computations before the page is sent to the client.
 
=== OODSL compiler for FPGA ===
An object oriented domain specific compiler was developed for programming Field Programmable Gate Arrays.<ref>Object-Oriented Domain Specific Compilers for Programming FPGAs[http://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=920835&userType=inst&tag=1]</ref> The compiler allows the hardware programmer to make use of object-oriented style while programming. The research paper claims that this way of programming the hardware brings down the time taken for design by several notches and still results in good optimal performance.
 
== Tools for Creating OODSL ==
When creating an OODSL, one can either choose to start from scratch or use a tool that is already available. Creating a language from scratch gives the programmer a certain amount of flexibility to define it the way he wants to, but it takes a lot of time. Therefore, in general, software tools are used to aid in the process of creating Domain Specific Languages. This is because it not only saves time, but also helps to make the language easy to use due to familiarity with the syntax of the underlying language.
=== Boo ===
Boo<ref>Boo Home[http://boo.codehaus.org/Home]</ref> is an open source object oriented language that is used to create Domain Specific languages. Defining basic data structures like array, hash, variables etc are inherently supported in Boo and it makes their creation easier. Although Boo is a statically typed language, these restrictions can be bent once in a while so that the type of objects can be found and manipulated in run time as well ([http://en.wikipedia.org/wiki/Duck_typing <code>Duck typing</code>]).
 
=== Visual Studio ===
Visual Studio has Domain-specific language tools that are designed to help the designer to build a language focusing on the language grammar and characteristics rather than paying much attention to the internal details of the compiler.<ref>Domain specific development[http://www.domainspecificdevelopment.com/]</ref> Visual tools are used that help focus on the business requirements of the OODSL rather than worrying about how it works internally.
=== Groovy ===
Groovy <ref>Groovy Home[http://groovy.codehaus.org/]</ref> is a dynamic language for the Java Virtual Machine. Also, the syntax is groovy is similar to that of Java, making designing of new OODSLs easier and similar to programming in Java. [http://java.dzone.com/articles/groovy-dsl-simple-example<code>An example for developing an OODSL in Groovy</code>].
 
== OODSL vs. non-OODSL ==
When defining a DSL, choosing whether to go with an OODSL or a non-OODSL depends on several factors like the domain for which it is defined, existing DSLs for that domain etc. Non-OODSLs are domain specific languages that do not necessarily embrace object oriented concepts like abstraction, polymorphism etc. OODSLs can be well suited for some situations whereas in other situations, they might be an overkill. Defining a new OODSL when there is an already widely accepted non-OODSL may not be very useful. For example, HTML is the standard method for displaying web pages and it is non-OODSL. Defining a new non-OODSL that replaces HTML may not prove to be significantly advantageous.
 
== Advantages and Disadvantages ==
Some of the advantages of OODSLs would be:
* Since OODSLs, by their name, are object oriented, they give the developer an easier alternative to model their applications based on business goals and using real world paradigms.
* Because of their object oriented nature, the code is generally simple to understand and therefore code maintenance would be easier in OODSLs than in non-OODSLs.
* Object oriented concepts like encapsulation and abstraction give the code better security when they are modified in the future.
 
 
Though OODSLs in general have several advantages over other languages, one must also consider their disadvantages:
* Defining an object oriented language in general takes more time than defining a normal language because we have to properly define it to include OO concepts.
* They may not be well-suited for all domains and environments. Sometimes there may be a simpler non-OODSL way to achieve the task.
 
== A Running Example ==
Given here is a simple example <ref>Example DSL in groovy[http://java.dzone.com/articles/groovy-dsl-simple-example]</ref> for creating an OODSL. The DSL defined here simply prints the text we have specified in the program. This is defined in [http://en.wikipedia.org/wiki/Groovy_(programming_language)<code>Groovy</code>].
 
The definition of our new OODSL is as follows:
<pre>
<pre>
package com.solutionsfit.dsl.memotemplate
class Example < ActiveRecord::Migration
import groovy.xml.MarkupBuilder
def self.up
class MemoDsl {
  create_table :first do ...
String toString
 
String fromString
  end
String messageString
  create_table
def sections = []
:second do ...
/**
* Make a closure. Main definition of the DSL program
  end
*/
end
def static make(closure) {
def self.down
MemoDsl memoDsl = new MemoDsl()
  drop_table :second
closure.delegate = memoDsl
  drop_table :first
closure()
end
}
end
/**
* Store the values in the local variables
*/
def to(String toString){
this.toString = toString
}
def from(String fromText){
this.fromString = bodyString
}
def message(String messageString){
this.messageString = messageString
}
/**
* The getText method gets called by the DSL by delegation
*/
def getText(){
doText(this)
}
private static doText(MemoDsl memodsl){
String template = "Memo\nTo: ${memoDsl.toText}\nFrom: ${memoDsl.fromText}\n${memoDsl.body}\n"
def sectionStrings =""
for (s in memoDsl.sections) {
sectionStrings += s.title.toUpperCase() + "\n" + s.body + "\n"
}
template += sectionStrings
println template
}
}
</pre>
</pre>
In the above example the up method is used for creating the tables first and second and the down method is used to dropping the tables. Now, consider a situation where there is a problem creating the second table. Then the database will contain only the first table and not the second table. So if you try to rollback the migration, it won’t work as the original migration failed and the schema version in the database
wasn’t updated. So you cannot roll back it. One solution to the above problem is, to manually change the schema information and drop the table first. But, it is recommended in these cases to simply drop the whole database, create the whole thing again and apply migrations to bring it back to the original state.
</p>
== Advantages of Migration ==
<ol>
<li>You can identify each migration and know when it has taken place.</li>
<li>Some migrations can also be rolled back. We can specify what the roll back procedure is.</li>
<li>Migrations can be managed with version control.</li>
<li>Automation – Automate things to be done which makes it reliably repeatable.  For example, In Ruby on Rails, we use Bundler instead of installing all gems manually. In short, specify what needs to be done and automate it.</li>
</ol>


A sample program in our newly developed OODSL would be:
== Disadvantages of Migration ==
<pre>
<ol>
package com.solutionsfit.dsl.memotemplate
<li>One drawback of Rails migrations is that all migrations occur at the database level, not the table level.</li>
<li>The whole discussion about Migration suggest that they are dangerous to use on production database. One should backup the database first and then use migrations on the production database.</li>
<li>Most databases do not prop up the rolling back of data definition language(DDL) statements.</li>
</ol>


class MemolDslTest extends GroovyTestCase {
== Conclusion ==
void testDslUsage_outputText() {
<p>
MemoDsl.make {
In a nutshell, Database Migration is a very efficient way to handle the discrepancies that occur between databases. i.e. changes made in one database not reflecting in other. It is a convenient way to alter the database in structured and organized manner. Rails migrations are mostly similar to version control of databases.  Rails migrations are database independent but SQL scripts are not.
to "Nirav Assar"
</p>
from "Barack Obama"
message "How are things? We are doing well. Take care"
text
}
}
}
</pre>


== References ==
== References ==
<references/>
<references/>
== Additional Reading ==
<ol>
<li>http://guides.rubyonrails.org/migrations.html#anatomy-of-a-migration</li>
<li>http://www.ibm.com/developerworks/java/library/j-cb08156/index.html</li>
<li>http://jacqueschirag.wordpress.com/2007/08/12/rants-about-rails-database-migrations</li>
<li>http://www.oracle.com/technetwork/articles/kern-rails-migrations-100756.html</li>
<li>Agile Web Development With Rails, Fourth Edition, Sam Rooby, Dave Thomas, David Heinemeier Hansson.</li>
</ol>

Latest revision as of 07:49, 3 October 2012

Saas 3.10 - Databases And Migrations

A Database<ref>http://en.wikipedia.org/wiki/Database</ref> is a coherent collection of data with inherent meaning. Random assortment of data is not a database. Data is organized in order to model relevant aspects of reality, so that it supports processes requiring this data. Data Migration is related to transfer of data between storage types, formats, or computer systems. This is performed programmatically to accomplish an automated migration so that humans are free from doing this repetitive task.

Database

A Database is nothing more than a collection of meaningful information. Databases can be of multiple types, for example Distributed Databases, Relational Databases, Flat File Databases. A database could be as simple as a text file with a list of names or it can even be very complex as a large relational database management system.
Examples:

  1. Banking Systems where accounts are maintained and it is made sure that money does not disappear as a result of system failure.
  2. Airline Reservation Systems where the plane details, the airport details and the customer details are maintained.
  3. Hotel Management Systems where the availability of rooms, the rates and the customer details are maintained.

Database Migration

Every application in reality has a database in the back end to store all the relevant data of the application. We should not test the application on database because it may contain valuable data like customer information in a banking system. So editing that data present in the database is not a good idea. The solution Rails<ref>http://guides.rubyonrails.org/getting_started.html</ref> provides for above problem is Defining three different environments: Development, Production and Testing each of which has a separate database and appropriate database types.

The Development Environment is what we use while developing the application. The production environment refers to the database that is used when the application is published in the real world. The testing environment is meant for testing tools. Testing of the application is done using Testing tools which automates the entire testing procedure. Since there are different databases in each environment, the problem that occurs is changes made in one Database do not reflect in the other.

A programmer is also responsible to tell the other developers what changes have been made in the database. Also one has to keep track of which changes need to be run against production machines during deployment. The solution for the above problem that rails offers is data migration. Databases of different types can also be migrated between the three different environments. For example, we may use SQLlite<ref>http://en.wikipedia.org/wiki/SQLite</ref> in Development environment, but we can still migrate into production environment where heroku<ref>http://en.wikipedia.org/wiki/Heroku</ref> may have been used. The source is portable and the back end understands what operations to do on the database.

In reality Rails migrations are similar to version control of databases. Rails migrations is actually used since databases change requires modifications to both code and data. Hence we cannot use a source code version control system like Subversion<ref>http://betterexplained.com/articles/a-visual-guide-to-version-control/</ref> or Sourcesafe<ref>https://wiki.library.ucsf.edu/display/~128507@ucsf.edu/Source+Safe+vs.+Subversion</ref>.

Creating A Migration

A migration is a sub class of ActiveRecord:: Migration which implements two methods: ‘up’ and ‘down’. The “up” method performs the required changes or transformations while the down methods reverses or roll backs them.

A migration can be created using the following command:

rake generate migration CreateCourse

Migration Created :

class CreateCourse < ActiveRecord::Migration
def up
 create_table :course do |t|
   t.string :name
   t.text :description
   t.timestamps
 end
end
def down
 drop_table :course
end
end

The above migration CreateCourse has just been created, but has not been applied to the Database yet. This migration will add a table called courses with string column called name and the text column called description. A primary key column called id will also be created by default. The time stamp columns created_at and updated_at which ActiveRecord populates automatically will also be added. Reversing this migration is nothing but dropping the table.

Migrations can also be used to fix bad data in the database or generate new fields.

For Example:

class AddGradesToStudents < ActiveRecord::Migration
def up
 change_table :students do |t|
   t.boolean :receive_grade, :default => false
 end
 User.update_all ["receive_grade = ?", true]
end
def down
 remove_column :students, :receive_grade
end
end

The above migration adds receive_grades to the students table. We want the default value to be false for new students. But existing students are considered to have a grade, So we use the student model to set the flag to true for existing students.

ActiveRecord<ref>http://api.rubyonrails.org/classes/ActiveRecord/Base.html</ref> provides methods that perform common data definition tasks in a database. A migration is like a Ruby class so you’re not limited to these functions. For example, after adding a column you can write a code to set the value of that column for existing records (if necessary using your models). The kind of object that is yielded as a result of the migration code is object representing table.

Updating Migrations

If you wish to make changes to the migration and you have already run the migration then you cannot just edit the migration and run it again. Rails will consider it has already run the migration, so it will do nothing on running “rake db:migrate”. The migration has to be rolled back and then make changes to the migration and run it. It is not recommended to edit existing migration and that too if it has been run on production systems. Instead, writing a new migration that performs the changes required is better. Making changes to a newly generated migration that has not been committed to source code is relatively safe.

Migrations are stored as files in the db/migrate directory, for every migration class. The name of the file is of the form YYYYMMDDHHMMSS_create_course.rb, that is nothing but a UTC timestamp identifying the migration followed by an underscore followed by the name of the migration.

Anatomy of Migrations

Migrations are a subclass of the Rails class ActiveRecord::Migration. The class must contain at least two methods i.e up and down.

class CreateCourses < ActiveRecord::Migration
def self.up
#...
end
def self.down
#...
end
end

The ‘up’ method used to apply schema changes for this migration and the ‘down’ method is used to undo the changes. Example: the ‘up’ method creates a table with all the attribute description for the migration whereas the ‘down’ method can be used to drop the table for the same migration.

Class CreateCourses < ActiveRecord::Migration
def self.up
       	add_column :room_no, :integer
end
def self.down
       	remove_column :room_no
end
end

Relationship between Model and Migration

In Rails, a model internally maps itself to a database table. The table in the database must be the plural form of the model’s class. If we generate a model called Course, Rails automatically looks for a table called courses in the database. You can use the Rails generator to generate both the model and a corresponding migration using the following commands:

rake generate model Course name: string description: text

will create a migration that looks like this

class CreateCourses < ActiveRecord::Migration
def change
  create_table :courses do |t|
	t.string :name
	t.text :description
 	t.timestamps
  end
end
end

Creating a Standalone Migration

If you are creating migrations for other purposes, then a migration generator is used:

$ rails generate migration AddSemesterToCourse

This will create an empty but appropriately named migration:

class AddPartNumberToProducts < ActiveRecord::Migration
def change
end
end

Applying Migration to Development

Since CreateCourse migration has been created but not applied to the database, the following command is used to apply the migration to the development database:

rake  db:migrate

Every Rails Database has a table called schema_migrations maintained by the migration code. Whenever a migration is applied successfully a new row will be added to schema_migrations table. The schema_migrations table has a version column. When you run rake db:migrate, the task first looks for the schema_migrations table. It will be created if it does not exist. The migration code then looks at all the migration files in db/migrate and skips from considering any that have a version number that is already in the database. It then continues by applying the remaining migrations in turn creating a new row in the schema_migrations table for every migration.

Applying Migration to Production

The following command is used to apply migration to the production database:

heroku rake db:migrate

In the above example the production database is Heroku.

Running Specific Migrations

If you need to run a specific migration up or down, the db:migrate:up and db:migrate:downtasks will do that on including the version also.

For example,

rake db:migrate:up VERSION=20080906120000

The above command will run the up method from the 20080906120000 migration. These tasks still check whether the migration has already run, so for example db:migrate:up VERSION=20080906120000 will do nothing if Active Record believes that 20080906120000 has already been run.

Rolling Back a Migration

The following command is used to rollback the last migration:

rake db:rollback

Rollback is performed when you made some mistake and instead of tracking down the version number of the previous migration, you can just rollback and run it after making changes.

If you need to rollback several migrations, a STEP parameter is used. For example,

rake db:rollback STEP=2

The above command will rollback the last 2 migrations. The db:migrate:redo task is an easy way for doing a rollback and then migrating again. If you need to redo several migrations, a STEP parameter is used. For example, in order to redo the last 4 migrations, the command is

rake db:migrate:redo STEP=4

“rake db:reset” is the command for resetting the database. This will drop the databse, recreate it and loads the current schema into it.

Problems with Migration

One major problem Migrations suffer is that most databases do not support the rolling back of create table or alter table i.e. DDL statements in general. Let’s consider an example where a migration tries to create two tables.

class Example < ActiveRecord::Migration
	def self.up
   	create_table :first do ...
	  
   	end
	   create_table
:second do ...
	
	   end
	end
	def self.down
   	drop_table :second
   	drop_table :first
	end
end

In the above example the up method is used for creating the tables first and second and the down method is used to dropping the tables. Now, consider a situation where there is a problem creating the second table. Then the database will contain only the first table and not the second table. So if you try to rollback the migration, it won’t work as the original migration failed and the schema version in the database wasn’t updated. So you cannot roll back it. One solution to the above problem is, to manually change the schema information and drop the table first. But, it is recommended in these cases to simply drop the whole database, create the whole thing again and apply migrations to bring it back to the original state.

Advantages of Migration

  1. You can identify each migration and know when it has taken place.
  2. Some migrations can also be rolled back. We can specify what the roll back procedure is.
  3. Migrations can be managed with version control.
  4. Automation – Automate things to be done which makes it reliably repeatable. For example, In Ruby on Rails, we use Bundler instead of installing all gems manually. In short, specify what needs to be done and automate it.

Disadvantages of Migration

  1. One drawback of Rails migrations is that all migrations occur at the database level, not the table level.
  2. The whole discussion about Migration suggest that they are dangerous to use on production database. One should backup the database first and then use migrations on the production database.
  3. Most databases do not prop up the rolling back of data definition language(DDL) statements.

Conclusion

In a nutshell, Database Migration is a very efficient way to handle the discrepancies that occur between databases. i.e. changes made in one database not reflecting in other. It is a convenient way to alter the database in structured and organized manner. Rails migrations are mostly similar to version control of databases. Rails migrations are database independent but SQL scripts are not.

References

<references/>

Additional Reading

  1. http://guides.rubyonrails.org/migrations.html#anatomy-of-a-migration
  2. http://www.ibm.com/developerworks/java/library/j-cb08156/index.html
  3. http://jacqueschirag.wordpress.com/2007/08/12/rants-about-rails-database-migrations
  4. http://www.oracle.com/technetwork/articles/kern-rails-migrations-100756.html
  5. Agile Web Development With Rails, Fourth Edition, Sam Rooby, Dave Thomas, David Heinemeier Hansson.