Rails Cookbook翻译(二)
处方3.2 编程式定义数据库模式
问题:
你正在为一个供销社开发一个基于Rails的应用程序,你想使用任何支持Rails migrations的数据库(例如:MySQL,PostreSQL,SQLite,SQL Server,and Oracle),你想定义你的数据库模式,而又不需要为特定的SQL数据库实现而担心。
解决方案:
在你的应用程序的根目录,运行generator命令:
$ ruby script/generate migration create_database
这个命令创建了一个新的名叫001_create_datebase.rb的migration脚本,在这个脚本的up方法中,添加使用Active Record模式语句创建模式的指令,例如create_table.在down方法中,我们作相反的工作:添加语句删除在up方法里创建的表。
db/migrate/001_create_database.rb
class CreateDatabase < ActiveRecord::Migration
def self.up
create_table :products do |t|
t.column :name, :string, :limit => 80
t.column :description, :string
end
create_table(:categories_products,:id=>false) do |t|
t.column :category_id, :integer
t.column :product_id, :integer
end
create_table :categories do |t|
t.column : name, :string, :limit => 80
end
end
def self.down
drop_table :categories_products
drop_table :products
drop_table :categories
end
end
然后使用migration来实例化你的数据库,通过运行:
$ rake db:migrate
讨论:
观察一下数据库,我们可以看见这些表被正确的创建,和你使用纯的SQL产生的效果是一样。
mysql> desc categories;
+-------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+----------------+
| id | int(11) | | PRI | NULL | auto_increment |
| name | varchar(80) | YES | | NULL | |
+-------+-------------+------+-----+---------+----------------+
2 rows in set (0.00 sec)
mysql> desc products;
+-------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+--------------+------+-----+---------+----------------+
| id | int(11) | | PRI | NULL | auto_increment |
| name | varchar(80) | YES | | NULL | |
| description | varchar(255) | YES | | NULL | |
+-------------+--------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)
mysql> desc categories_products;
+-------------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------+---------+------+-----+---------+-------+
| category_id | int(11) | YES | | NULL | |
| product_id | int(11) | YES | | NULL | |
+-------------+---------+------+-----+---------+-------+
2 rows in set (0.00 sec)
我们已经创建了一个在products和categories表之间具有多对多关系的数据库,以及一个categories连接表。不像其他表,连接表是没有主键的。当我们创建categories_products时,我们通过向create_table传递@:id => false的选项就废弃了Rails会默认创建的主键,
create_table占用一个块,他包含了对column方法的调用,把列的名传递给该方法定义了表的列.column ,接着是类型,例如::primary_key,:string,:text,:integer,:float,:datetime,:timestamp,:time,:date,:binary,:boolean。最后,你可以向column方法传递一些选项作为参数来定义字段的最大宽度,默认值,是否允许为null。例如:
t.column :name, :string, :limit => 80
t.column :role, :string, :default => ‘admin’
t.column :status, :string, :default => ‘pending’,:null => false