Agile Web Development with Rails 翻译(九)
第六章 任务 A: 产品管理
我们第一个开发任务是创建web接口来管理我们的产品信息—创建新产品,编辑现有品,删除不需要的产品,等等。我们将以最小的反复来开发这个应用程序,最小意味着“以分钟衡量”。现在开始吧!
6.1 循环 A1: 让某些东西运行起来
我们开始创建一个新的Rails应用程序。在这儿做完我们的所有工作。下面,我们要创建个数据库来保存我们的信息 (事实上,我们创建了三个数据库)。 一旦地基打好了,我们就可以
1、创建保存产品信息的表。
2、配置我们的Rails以让它指向我们数据库,并
3、由Rails生成产品管理应用程序的最初版本。
创建Rails应用程序
回到25页,我们看看如何创建个新的Rails应用程序。进入命令行窗口,输入下面rails命令,在这个例子中,们的工程被称为depot,所以输入:
work> rails depot
我们看到很多输出。当完成时,我们发现有个新目录,depot,被创建了。这就是我们开始工作的地方。
work> cd depot
work> ls
CHANGELOG app db log test
README components doc public vendor
Rakefile config lib script
创建数据库
对这个应用程序,我们将使用开源的MySQL数据库服务(如果你使用随后的代码,那么你也需要它)。我们实际上创建了三个数据库:
1、depot_development 将是我们的开发者数据库。我们程序的工作就在这儿完成。
2、depot_test 是测试数据库。它被认为暂时的。
3、depot_production 是产品数据库。当放到线上时,我们应用程序将使用它。
我们使用mysql的命令行客户端来创建我们数据库,但如果你有更合适的工具如phpmyadmin或者CocoaMySQL,那么使用它。
depot> mysql -u root -p
Enter password: *******
Welcome to the MySQL monitor. Commands end with ; or g.
mysql> create database depot_development;
mysql> create database depot_test;
mysql> create database depot_production;
mysql> grant all on depot_development.* to 'dave'@'localhost';
mysql> grant all on depot_test.* to 'dave'@'localhost';
mysql> grant all on depot_production.* to 'prod'@'localhost' identified by 'wibble';
mysql> exit
创建产品表
回到47页的图5.3,我们勾出了产品表基本内容。现在让我们进行实操。这儿MySQL内的用于创建产品表的DDL语言。
drop table if exists products;
create table products (
id int not null auto_increment,
title varchar(100) not null,
description text not null,
image_url varchar(200) not null,
price decimal(10,2) not null,
primary key (id)
);
我们的表包括产品的title,description,image,和price,就像我们草图中一样。我们也可以添加些新内容:id。它用于给出表内每行的唯一键,允许其它表引用产品。缺省地,Rails假设它处理的每个表都有它自己的主键,一个叫id的整数列。[注意,大小写是很重要。如果你使用一个过时的GUI工具插入列名为Id,你会有麻烦的。]在内部,Rails使用这个列的值来保持对它从数据库加载数据的跟踪,并将数据与不同的表连接起来。你可以重新定义这个系统的名字,但除非你使用Rails的逻辑计划来工作,它不会让你修改,我们推荐你只使用名字id。
可以很好地为产品表使用DDL,但是我们应该把它存在哪儿?我坚信把DDL保存在应用程序的数据库是最好的,所以我总是用文本文件创建它。对于一个Rails应用程序来说,我调用创建的.sql文件,并把它放到我的应用程序的db子目录内。这让我使用mysql客户端来运行DDL,并在开发者数据库内创建表。再说一次,如果你喜欢的话,你可以自由地使用GUI或基于web的工具。
depot> mysql depot_development <db/create.sql
配置应用程序
在很多脚本语言的Web应用程序中,如何连接数据库的信息被直接地植入到代码中—你可以发现对connect()方法的调用,传递主机和数据库名字,随后是用户名和口令。这是危险的,因为口令信息会被放在web可访问目录的一个文件中。一个小的服务配置错误可能会将你的口令显露给全世界。
将连接信息植入到代码中也很不灵活。一旦你想使用开发者数据库做你的hack away。那么当你下次想运行同样代码时要再次测试数据库。最后,你会想配置它到发布的产品中。每次你切换目标数据库时,你必须编辑连接调用。程序规则会说,你将丢失口令,在切换应用程序到发布的产品中时。
聪明的开发者在代码外部保存连接信息。时候你可能想使用一些仓库来保存它(Java开发者通常使用JNDI来查看连接参数)。这对一般的web应用程序来说还显笨重,所以Rails简单地使用一个文本文件。你将在config/database.yml中找到它[.yml是YAML名字的一部分,YAML不是Markup语言。它只是在文本文件(不是XML)内简单存储结构信息。最新的Ruby版本内建了对YAML的支持。]
如图6.1所示,database.yml有三个部分,分别是development,test和production数据库。使用编辑器修改每个字段以与我们创建的数据库相匹配。注意,在新的database.yml文件中我们让development和test环境下的username字段为空。这是很方便的,因为它意味着不同的开发者将分别使用自己的username来连接。但是,我们应该报告一些与MySQL相关的东西,数据库驱动程序,和操作系统,并让这些字段为空,这样Rails会试着以root身份连接数据库。如在Access数据库中没有’root’@’localhost.localdomain’用户,你会得到一个错误,此时在这两个字段放置明确的username。
创建维护应用程序
现在,所有工作都做完了。我们将Depot应用程序设置成一个Rails工程。我们已经创建了数据库和产品表。并且我们配置了我们程序对数据库表的连接。现在写维护应用程序。
depot> ruby script/generate scaffold Product Admin
dependency model
exists app/models/
exists test/unit/
exists test/fixtures/
create app/models/product.rb
create test/unit/product_test.rb
: :
create app/views/admin/show.rhtml
create app/views/admin/new.rhtml
create app/views/admin/edit.rhtml
create app/views/admin/_form.rhtml
现在这还不是最难的,是吗? [除非,或许你运行在OS X10.4上。它似乎去掉了Ruby标准的MySQL库。如果更新“支架”前你看到错误信息,那么试着为你的“模型”(Product)创建一个表,就可以了,这是因为Ruby(还有Rails)不能进入数据库造成的。要修正Apple的错误安装,你需要重新安装Ruby的MySQL库,这意味着你要回到21页,运行脚本来修复Ruby安装,然后重新安装mysql gem。][一些读者也说得到这样的错误,客户端不支持由服务端发出的签定协议请求;可考虑升级MySQL客户端。这可能是由于MySQL安装版本和用于访问它的库不兼容造成的,可按照http://dev.mysql.com/doc/mysql/en/old-client.html的说明来解决。并可用MySQL命令如设置口令的’some_user’@’some_host’ = OLD_PASSWORD(’newpwd’)。]
这个命令写了一个基本的维护应用程序。Product参数告诉此命令我们需要的“模型”的名字,并且Admin参数指出了“控制器”的名字。现在让我们试试新应用程序。首先,我们要启动本地的支持Rails的WEBrick Web服务。
depot> ruby script/server
=> Rails application started on http:// 0.0.0.0:3000
[2005-02-08 12:08:40] INFO WEBrick 1.3.1
[2005-02-08 12:08:40] INFO ruby 1.8.2 ( 2004-12-30) [powerpc-darwin7.7.0]
[2005-02-08 12:08:40] INFO WEBrick::HTTPServer#start: pid=20261 port=3000
就像我们在第四章做的demo应用程序一样,这个命令启动了一个本地主机的Web服务,端口是3000。[有时当你试着运行WEBrick时,你可能会得到一个错误,说地址已经在使用。这说明你在本机上已经有了一个Rails WEBrick服务。如果你在按本书的例子来做,就可以是第四章的Hello,World!应用程序。先关闭它,然后按Ctr-C杀掉服务。]让我们连接它。记住我们在浏览器给出的URL包含了端口号(3000)和小写(admin)的“控制器”名字。
很好,它显示给我们产品列表,但是那儿没有任何产品。让我们补上一些,单击New product连接,会出现图6.2样的表单来显示我们应该填充的。单击Creat 按钮,你应该看到列表内的新品(图6.3)。或许界面不是很好,但它可以工作,并且我可以显示它给我们的客户来确认。它们可能按下其它连接(如图6.4中的查看细节,编辑现有产品等等)。我们解释说这只是第一步—我们知道程序是正确的,但我们想早些得到它们的反馈信息。
Rails 的“支架”(Scaffolds)
在这个简短的实现中我们隐藏了些细节,所以让我们花些时间来看看更详细的一步。Rails“支架”是为管理一个“模型”而自动创建的一个框架。当我们运行“生成器”时,我们告诉它我们需要一个“支架”来生成一个特殊的“模型”(由“支架”创建的),并且我们需要通过给定的“控制器”(也是由“支架”创建的)来访问它。
在Rails中,“模型”被自动地映射到使用“模型”的类的名字的复数形式的数据库表。在我们例子中,我们要求一个名为Product的“模型”,所以Rails将它与叫products的表关联起来。Rails是如何找到那个表的呢?当我们在config/database.yml中设置development条目时,就已经告诉Rails在哪儿找数据库的表了。当我们启动应用程序时,“模型”检查数据库内的表,处理它要列,然后创建数据库表和Ruby对象间的映射。
2006年4月16日更新