Migrations¶
Creating new tables¶
Migrations are one more rails feature that makes developing less painful. With them you don't need to write SQL to set up tables in databases for every environment. Lets see how.
Suppose, we create a new model Book with attributes title, published year, and isbn:
ruby script/generate model book title:string, published_year:integer, isbn:string
exists app/models/
exists test/unit/
exists test/fixtures/
create app/models/book.rb
create test/unit/book_test.rb
create test/fixtures/books.yml
create db/migrate
create db/migrate/20090801123115_create_books.rb
The last line shows us that rails created migration file for our new model. Migration files live under db/migrate.Lets study what is inside this file:
class CreateBooks < ActiveRecord::Migration
def self.up
create_table :books do |t|
t.string, :title
t.integer, :published_year
t.string, :isbn
t.timestamps
end
end
def self.down
drop_table :books
end
end
We see here that the class CreateBooks inherits from ActiveRecord::Migration.
Then two methods defined: self.up and self.down (actually, up and down). Up is called when this migration is added to the database. Down is called when a migration is undone (or reversed).
The Up method starts with create_table method, which tells rails to create new table with name 'books'. As you may recall, the table name should be pluralized version of model name. Then in a block it passes attributes of table: columns and their types. In old resources you may find another way of attribute definition:
create_table :books do |t|
t.column :title, :string
t.column :published_year, :integer
t.column :isbn, :string
This was the format for migrations before rails 2.0. Although, this format will still work.
t.timestamps is a magic method that creates two columns: updated_at and created_at.
The Down method only contains one line with method drop_table, that tells rails to drop table with name 'books'.
For relations like HABTM you don't need column id for table. Just tell rails not to create this column:create_table :books_authors, :id => false do |t|
Altering tables with migrations¶
In the development process sometimes we need to add columns to table or add table for HABTM relationship. So we don't need to generate a model, just the database migration.
Rails provides special generator for this: script/generate migration.
ruby script/generate migration AddDescriptionToBook description:text
exists db/migrate
create db/migrate/20090801140441_add_description_to_book.rb
Notice that the name passes the script/generate migration AddDescriptionToBook gives the generator some clues as to what you will be doing in that migration so it will automatically generate the up and down methods with what it believes you are trying to do in that migration.
If you look at the a generated migration file 20090801140441_add_description_to_book.rb:class AddDescriptionToBook < ActiveRecord::Migration
def self.up
add_column :books, :description, :text
end
def self.down
remove_column :books, :description
end
end
You will see that the Up method adds column (with method add_column) to table books, that title for the column is description and its type is text.
The Down method removes column description from table books.
class AddDescriptionToBook < ActiveRecord::Migration
def self.up
change_table :books do |t|
t.text :description
end
end
def self.down
change_table :books do |t|
t.remove_column :description
end
end
Adding index with migration¶
One of the ways to improve performance of your app is through optimization of database with indexes.
ActiveRecord::Migration provides method add_index to add an index to the database and method remove_index to remove it.
class CreateBooks < ActiveRecord::Migration
def self.up
create_table :books do |t|
t.string, :title
t.integer, :published_year
t.string, :isbn
t.timestamps
end
add_index :books, :title
end
def self.down
drop_table :books
remove_index :books, :title
end
end
Rake tasks to work with migrations¶
To see all available rake tasks for database type
rake -T db
If you have filled file config/database.yml with credentials to work with your database,then you can tell rails to perform actions with it.
To create the database:
rake db:createto create database for current environment (default = development). or
rake db:create:allto create databases for all environments. To drop the database for the current environment enter:
rake db:dropor for all environments:
rake db:drop:all
To perform migrations from db/migrate :
rake db:migrate.
If you want to rollback to specified version of migration, type:
rake db:migrate VERSION=20090801140441
