Googlier.com News Article Search
Googlier.com Precious Metals Exchange Smart Contracts
Googlier.com Document Services





          Ruby on Rails Migration      
http://staffofgeeks.net/afeng/archive/2006/09/30/92832.aspx

Originally posted on: http://staffofgeeks.net/afeng/archive/2006/09/30/92832.aspx

Recently I decided to check out the beta version of Agile Web Development with Rails book, which is targeted to be released this fall.  It is very interesting that the authors also brought agility into book writing.  It allows readers to provide feedback to new material during the development of the book.  I am also glad to see that the migration part of the framework has become a big part of the book, even having a separate chapter dedicated to it.  It uses migration instead of DDL in the entire demo application.  Besides the migration, there are many significant updates to various parts of the book. But in this post, I will focus mostly on the migration tool.

The migration tool is targeting Rails applications, but it can also be useful outside the Rails world.  There are some people out there already (includes us, here is my old post on it) experimenting using Rails migration as "Enterprise glue" to maintain database schemas.  I hope the final release version of the book will have something on this topic.

I will outline the basics of rails migration below for those are not familiar with it.

What is Ruby on Rails Migration?

At the most simple level, it allows developers to change the database schema as the application requires it in a simple and easy manner.  Instead of writing DDL scripts, you use Ruby as a DSL (domain specific language) to describe what the schema should look like when the changes are required.

Why use it?

The migration tool allows developers to upgrade or downgrade a schema version without loosing data (of course, if you drop stuff it will be lost).  Sure, you can write DDL that does the same thing for you (sort of, but not really without some external tooling), but it will take a lot more effort especially when you are supporting more than one database.  In theory, the migration script you write for one database should work on other databases as long as the operation is supported (currently, it supports all major databases including open source alternatives).  I said in theory because not all databases behave exactly the same way for a given operation. There might be some minor differences, but that's for another post.  If you need to extend or change the existing migration functionality, it is usually very easy to do so.

How does it work?

You basically write a Ruby class that inherits from ActiveRecord::Migration to describe what needs to be accomplished.  There are only two methods you need to write, up and down.  Up method will be called during an upgrade, and down method for downgrading.

class AddTable < ActiveRecord::Migration
  def self.up
    create_table :cars do |t|
      t.column :model,       :string
      t.column :year,          :int
      t.column :make,        :string
      t.column :comments, :text
    end
  end
 
  def self.down
    drop_table :cars
  end
end

In this trivial example, it creates a cars table with model, year, make, and comments columns.  One interesting thing to note about model and make columns are both string type.  This is not DDL we are working with.  Migration uses Ruby classes to encapsulate the internal database types in order to abstract out the databases.  Depending on what type of database you are using, string type might vary, but it tends to be pretty consistant across different databases.  In the down method, it just does exactly the opposite, as if the script has never been run.

On the command line, if you run “rake db:migrate”, your database will be upgraded to the latest version.  In this case, the cars table will be added.  Each migration script will have a 3 digit number in the start of the file name which represents the schema version of the script.  That same version number is also stored in the database you are using.  That is how migration knows which script to run during an upgrade or downgrade.  Using the example above, the file name would look something like the following:

001_create_cars.rb

Lets say you are currently on version four but you need to roll back to version one, you can run the following command:

rake db:migration VERSION=1

Migration supports most of the operations you would need to perform on the daily basis.  But if you need to do something it does not support you can always execute DDL in your migration script.

One of the really cool things about using Ruby as a DSL is that you have the power of a real programming language to create your migration scripts. This comes in really handy when you need to create test data.

I only scratched the surface on the stuff I covered on Rails migration.  I would encourage anyone that is interested to read the Rails book.




Array ( [nbsp] => 83 [the] => 49 [p] => 38 [to] => 29 [you] => 19 [a] => 18 [of] => 17 [migration] => 16 [it] => 16 [br] => 13 [is] => 12 [on] => 12 [are] => 11 [in] => 9 [I] => 9 [will] => 9 [be] => 9 [Rails] => 8 [version] => 8 [database] => 8 [as] => 7 [book] => 7 [but] => 6 [for] => 6 [need] => 6 [script] => 6 [strong] => 6 [that] => 6 [Ruby] => 6 [Migration] => 6 [DDL] => 5 [t] => 5 [and] => 5 [not] => 5 [databases] => 5 [this] => 5 [cars] => 5 [http] => 5 [run] => 4 [also] => 4 [In] => 4 [end] => 4 [using] => 4 [down] => 4 [schema] => 4 [with] => 4 [can] => 4 [afeng] => 4 [does] => 4 [table] => 4 [column] => 4 [write] => 4 [if] => 4 [string] => 4 [create] => 4 [net] => 4 [same] => 3 [allows] => 3 [tool] => 3 [during] => 3 [post] => 3 [when] => 3 [archive] => 3 [staffofgeeks] => 3 [one] => 3 [really] => 3 [what] => 3 [do] => 3 [href] => 3 [some] => 3 [make] => 3 [have] => 3 [something] => 3 [out] => 3 [rails] => 3 [model] => 3 [type] => 3 [would] => 3 [which] => 3 [or] => 3 [method] => 3 [There] => 3 [It] => 3 [upgrade] => 3 [your] => 3 [like] => 2 [scripts] => 2 [That] => 2 [use] => 2 [following] => 2 [DSL] => 2 [should] => 2 [look] => 2 [change] => 2 [language] => 2 [most] => 2 [simple] => 2 [easy] => 2 [developers] => 2 [describe] => 2 [example] => 2 [downgrade] => 2 [ActiveRecord] => 2 [comments] => 2 [columns] => 2 [year] => 2 [One] => 2 [about] => 2 [self] => 2 [def] => 2 [This] => 2 [command] => 2 [rake] => 2 [an] => 2 [db] => 2 [up] => 2 [only] => 2 [class] => 2 [data] => 2 [number] => 2 [might] => 2 [exactly] => 2 [all] => 2 [supports] => 2 [currently] => 2 [operation] => 2 [work] => 2 [file] => 2 [more] => 2 [thing] => 2 [stuff] => 2 [name] => 2 [drop] => 2 [theory] => 2 [without] => 2 [very] => 2 [aaronfeng] => 2 [com] => 2 [writing] => 2 [part] => 2 [has] => 2 [interesting] => 2 [uses] => 2 [application] => 2 [there] => 2 [img] => 2 [aspx] => 2 [But] => 2 [The] => 2 [src] => 2 [real] => 1 [internal] => 1 [jpg] => 1 [note] => 1 [o] => 1 [both] => 1 [windows] => 1 [core] => 1 [we] => 1 [working] => 1 [classes] => 1 [encapsulate] => 1 [types] => 1 [creates] => 1 [order] => 1 [abstract] => 1 [Depending] => 1 [vary] => 1 [read] => 1 [tends] => 1 [interested] => 1 [pretty] => 1 [consistant] => 1 [across] => 1 [different] => 1 [align] => 1 [left] => 1 [opposite] => 1 [beta] => 1 [Up] => 1 [fall] => 1 [called] => 1 [released] => 1 [downgrading] => 1 [AddTable] => 1 [lt] => 1 [targeted] => 1 [Development] => 1 [Web] => 1 [Agile] => 1 [title] => 1 [trivial] => 1 [width] => 1 [pragmaticprogrammer] => 1 [www] => 1 [aggbug] => 1 [check] => 1 [decided] => 1 [int] => 1 [Recently] => 1 [border] => 1 [text] => 1 [vspace] => 1 [just] => 1 [never] => 1 [power] => 1 [roll] => 1 [knows] => 1 [Using] => 1 [above] => 1 [posted] => 1 [comes] => 1 [Originally] => 1 [rb] => 1 [Lets] => 1 [say] => 1 [four] => 1 [back] => 1 [how] => 1 [VERSION] => 1 [operations] => 1 [perform] => 1 [daily] => 1 [basis] => 1 [support] => 1 [always] => 1 [execute] => 1 [programming] => 1 [cool] => 1 [things] => 1 [handy] => 1 [stored] => 1 [been] => 1 [upgraded] => 1 [blob] => 1 [On] => 1 [gwb] => 1 [line] => 1 [ldquo] => 1 [anyone] => 1 [hspace] => 1 [migrate] => 1 [rdquo] => 1 [alt] => 1 [encourage] => 1 [latest] => 1 ['http] => 1 [case] => 1 [added] => 1 [Each] => 1 [covered] => 1 [digit] => 1 [surface] => 1 [scratched] => 1 [start] => 1 [test] => 1 [aspx'] => 1 [represents] => 1 [experimenting] => 1 [needs] => 1 [methods] => 1 [many] => 1 [Instead] => 1 [applications] => 1 [targeting] => 1 [mostly] => 1 [domain] => 1 [specific] => 1 [focus] => 1 [parts] => 1 [various] => 1 [updates] => 1 [significant] => 1 [changes] => 1 [useful] => 1 [required] => 1 [Why] => 1 [Besides] => 1 [demo] => 1 [loosing] => 1 [entire] => 1 [course] => 1 [instead] => 1 [dedicated] => 1 [lost] => 1 [Sure] => 1 [chapter] => 1 [manner] => 1 [outside] => 1 [having] => 1 [basics] => 1 [glue] => 1 [maintain] => 1 [old] => 1 [schemas] => 1 [hope] => 1 [final] => 1 [release] => 1 [my] => 1 [here] => 1 [topic] => 1 [outline] => 1 [below] => 1 [requires] => 1 [html] => 1 [those] => 1 [blogspot] => 1 [familiar] => 1 [What] => 1 [At] => 1 [us] => 1 [includes] => 1 [level] => 1 [already] => 1 [people] => 1 [world] => 1 [separate] => 1 [even] => 1 [two] => 1 [functionality] => 1 [provide] => 1 [way] => 1 [given] => 1 [readers] => 1 [minor] => 1 [differences] => 1 [that's] => 1 [another] => 1 [If] => 1 [extend] => 1 [existing] => 1 [usually] => 1 [because] => 1 [into] => 1 [so] => 1 [How] => 1 [You] => 1 [basically] => 1 [agility] => 1 [inherits] => 1 [from] => 1 [brought] => 1 [Enterprise] => 1 [accomplished] => 1 [authors] => 1 [behave] => 1 [said] => 1 [sort] => 1 [see] => 1 [big] => 1 [external] => 1 [tooling] => 1 [take] => 1 [lot] => 1 [become] => 1 [effort] => 1 [especially] => 1 [supporting] => 1 [than] => 1 [framework] => 1 [glad] => 1 [alternatives] => 1 [other] => 1 [am] => 1 [long] => 1 [development] => 1 [supported] => 1 [material] => 1 [new] => 1 [feedback] => 1 [major] => 1 [including] => 1 [open] => 1 [source] => 1 [height] => 1 )

© Googlier LLC, 2019