2.3. Schema
Migrations
Here, we'll create and configure the development
database. We assume that you're working from the MySQL command
prompt, but you can easily use another database and any alternative
user interface that allows you to update the schema. Keep in mind
that it's often useful to be able to execute scripts to create your
development database and test data.
|
Do not configure your test database as your
production or development database. All data in your test database
is replaced each time you execute a new test.
|
|
|
Rails has three environments: development,
test, and production. The Rails environment called
development reloads classes each time you call a new action, so you
get a fresh copy of each class, including any recent development
changes. The production environment loads classes once. With this
approach, development performance is worse, but you get rapid
turnaround time between making a change and seeing results in your
browser.
You also get separate development, production,
and test databases. Sane developers don't want to use production
databases to write code, because they don't want to create, modify,
or destroy production data. But why would Rails support a separate
test database? In Chapter 7, you'll see
that for each new test, Rails creates a fresh copy of test data, so
each test case can modify database data without affecting other
tests.
When Rails generates a new project, it creates a
file called database.yml with
sections for development, test, and production. You'll need to keep
a couple of things in mind as you configure a database. First,
because Rails destroys the data in the test database, you need to
make sure that you don't point this test configuration at your
development or production databases. Second, this file has
passwords, in plain text. Make sure you handle them
appropriately.
|
You'll need an Active Record model object. Don't
worry about the details yet; we'll cover them later. For now, just
generate the model object by typing:
> ruby script/generate model Photo
exists app/models/
exists test/unit/
exists test/fixtures/
create app/models/photo.rb
create test/unit/photo_test.rb
create test/fixtures/photos.yml
create db/migrate
create db/migrate/001_create_photos.rb
Rails generated a model object in app/models/photo.rb, but it won't work without
a schema.
So, you have a decision to make. You can manage
the schema with SQL scripts or with migrations. If you decide to
use simple SQL scripts, you'll need to create database-specific
schemas, and you'll probably wind up creating new test data
whenever you create a new table. Rails gives a better option:
schema migrations. You'll have to
do a little more work up front, but you'll be able to specify
database-independent schemas and improve your database without
losing data. The first step is to create a database; then, create a
migration for each change you want to make to the database.
To use schema migrations, you'll also need to
configure Active Record to use Ruby schemas instead of SQL scripts.
If you're running Rails 1.0 or before, edit the config/environment.rb file, and set
active.record.schema.format to :ruby, like
this:
config.active_record.schema_format = :ruby
If you're running Rails 1.1 or later, you don't
need to do anything because :ruby schemas are the default.
Each change you make to the database schema has an up
method to make the change, and a down method to undo the
change.
Now that we've configured the database, we need
a migration. Beginning with Rails 1.1, the model generator creates
a migration for you. Look in db/migrate, and you'll find a migration called
001_create_photos.rb. You'll also see methods called
up and down. Edit them to look like this:
class CreatePhotos < ActiveRecord::Migration
def self.up
create_table "photos" do |photo|
photo.column "filename", :string
end
end
def self.down
drop_table "photos"
end
end
The schema migrations feature keeps track of a
list of migrations, and each migration has an associated version
number. The up method creates a photos table with two
columns, filename and id, and the down method removes it.
Each schema migration has steps to do and undo a change. You can
include changes that you need to make in data as well. Then, if you
need to move back to a previous version, you can do so. But now, we
need to run the migration. Type this:
> rake migrate
== CreatePhotos: migrating ====================================================
-- create_table("photos")
-> 0.1250s
== CreatePhotos: migrated (0.1250s) ===========================================
You should now verify that Rails created the
database schema. Go to the MySQL command prompt, use the
photos_development database, and show the tables:
>mysql -u root photos_development
Welcome to the MySQL monitor. Commands end with; or \g.
Your MySQL connection id is 46 to server version: 5.0.16-nt
Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
mysql> show tables;
+------------------------------+
| Tables_in_photos_development |
+------------------------------+
| photos |
| schema_info |
+------------------------------+
2 rows in set (0.00 sec)
Active Record created two tables:
schema_info and photos. In schema_info,
Active Record will keep track of the state of the existing version
number. You'll be able to keep track of photos using the
photos database and keep track of each schema change on
that table with a migration. Because migrations handle both data
and schema, you'll be able to maintain data across your
migrations. |