In my previous post on migrations i wrote that “…they are not covered in any of the basic books on RoR”. Well, this statement does not hold anymore, since Agile Web Development with Rails, 2nd ed. is already creating the models with migrations.
While the last part of the post (why are migrations so cool) is still up-to-date, they way of creating migrations is different from 1.1 on, so i have decided to review the topic and add some new points, too.
Migrations are now created automatically with the model
In my previous post, i have been creating the migration manually with the command
ruby script/generate migration ProductMigration
However, as of Rails 1.1, you don’t have to do this anymore. When you generate the model (let’s stick with the Product model as an example) the migration is automatically generated:
ruby script/generate model Product ... ... #some lines omited ... create db/migrate/001_create_products.rb
Now you can edit the file db/migrate/001_create_products.rb to contain something like this:
class ProductMigration < ActiveRecord::Migration def self.up create_table :products do |table| table.column :title, :string table.column :description, :text table.column :image_url, :string end (rest of the file omited)
To update the database. That's even easier than in the previous versions of rails!
Valid column data types and possible options
Valid columns are:
integer, float, datetime, date, timestamp, time, text, string, binary and boolean.
Valid column options:
- limit ( :limit => â€œ50â€ )
- default (:default => â€œblahâ€ )
- null (:null => false implies NOT NULL)
string is the equivalent of varchar(255), so if you would like to have a string column (called title) of length 100 instead of 255, with default value 'Some title' and to forbid NULL value, you have to type
table.column :title, :string, :limit => 100, :default => "Some title", :null => false
Generating test data
I am quite sure you know the situation when you want to test something quickly and you waste precious time to generate some test data, which you trash after the testing just to find yourself in the same situation later?
Well, migrations can help you to prevent headaches because of this, too. Here is how:
ruby script/generate migration create_test_data Create db/migrate/002_create_test_data.rb
You can create test data inside the migration file like this:
class ProductMigration < ActiveRecord::Migration def self.up Product.create(:title => 'My cool book about the meaning of life', :description => '42', :image_url => /images/cool_book42.png)
You can now commit this migration to the RCS you are using, and modify/add more test data later.
The other advantage is that your colleagues won't spend time writing dummy test data either: they can just check out this migration and happily use the provided tests.
If this is still not enough for you...
You can write SQL statements inside the migrations. For example:
execute "alter table items add constraint fk_items_products foreign key (product_id) references products(id)"
However, use this with care since you have to write native DDL statements, which violates one of the fundamental 'cool factors' of migrations: independence from DB vendors.
The Agile Web Development with Rails, 2nd ed can be considered as the Rails bible and since it is promoting migrations as the definitive way to handle your DB issues, i think migrations will become (in fact the already did for lots of people) the state of the art. After using them for a while and enjoying the power and flexibility they provide without having significant drawbacks, i don't really see why should one not use them in the future.