简单开始
下载并且安装
Ruby 1.8.4;
RubyGems;
通过命令行安装所有的Rails和其依赖:
gem install rails --include-dependencies
在用户工作目录运行命令行,即创建第一个rails的模板:
rails depot
cd depot
ruby script/server
在浏览器打开 http://localhost:3000 即可发现第一个rails的web应用已经开始run起来了。
然后我参考书籍《Agile Web Development with Rails》2nd Edition的第一个例子一步一步的动手写了第一个ROR程序。(具体的过程不详细记录了.)
从数据库准备、数据库的配置、创建表、migrate、创建controller和maintenance、add missing column、添加validation功能、使用scaffold、定制html、装填unit test数据。整个例子的思路比较清晰,从数据库、数据访问、业务、controller、展示;给我留下深刻的影响的是:自动生成功能、内嵌web server、支持数据库配置,支持应用的模板、支持mvc模板等,所以让人似乎感觉到一些DSL的色彩。
做一个复杂一些的例子
数据库准备
支持数据库Mysql,从 http://dev.mysql.com/downloads/mysql/5.0.html#downloads 下载数据库Mysql安装,并且下载Mysql Administrator作为数据库管理工具。
创建Schema为:
depot_dev
在文件./config/database.yml中对数据库进行配置:
development:
adapter: mysql
database: depot_dev
username: depot
password: depot
host: localhost
测试配置:
rake db:migrate
如果配置不正确在控制台会出现错误的日志。
创建Products的Model和Table如下:
D:\IDE\rails-exampe\depot>ruby script/generate model product
输出:
exists app/models/
exists test/unit/
exists test/fixtures/
create app/models/product.rb
create test/unit/product_test.rb
create test/fixtures/products.yml
create db/migrate
create db/migrate/001_create_products.rb
在./db/migrate/001_create_products.rb用类似DDL的形式表达表的结构:
class CreateProducts < ActiveRecord::Migration
def self.up
create_table :products do |t|
t.column :title, :string
t.column :description, :text
t.column :image_url, :string
end
end
def self.down
drop_table :products
end
end
Okey,那就Migrate吧:
D:\IDE\rails-exampe\depot>rake db:migrate
输出:
D:0:Warning: require_gem is obsolete. Use gem instead.
(in D:/IDE/rails-exampe/depot)
== CreateProducts: migrating ==================================================
-- create_table(:products)
-> 0.0780s
== CreateProducts: migrated (0.0780s) =========================================
数据库一切搞定,下一步开始应用层了,首先创建Controller:
D:\IDE\rails-exampe\depot>ruby script/generate controller admin
输出:
exists app/controllers/
exists app/helpers/
create app/views/admin
exists test/functional/
create app/controllers/admin_controller.rb
create test/functional/admin_controller_test.rb
create app/helpers/admin_helper.rb
创建Maintenance应用:
编辑app/controller/admin_controller.rb
class AdminController < ApplicationController
scaffold :product
end
启动ruby script/server,通过浏览器就可以浏览这个Rail scaffolds的应用了。
迭代2:Add a missing column
D:\IDE\rails-exampe\depot>ruby script/generate migration add_price
exists db/migrate
create db/migrate/002_add_price.rb
编辑db/migrate/002_add_price.rb
class AddPrice < ActiveRecord::Migration
def self.up
add_column :products, :price, :decimal, :precision => 8, :scale => 2, :default => 0
end
def self.down
remove_column :products, :price
end
end
执行命令:
D:\IDE\rails-exampe\depot>rake db:migrate
输出:
D:0:Warning: require_gem is obsolete. Use gem instead.
(in D:/IDE/rails-exampe/depot)
== AddPrice: migrating ========================================================
-- add_column(:products, :price, :decimal, {:default=>0, :precision=>8, :scale=>2})
-> 0.2650s
== AddPrice: migrated (0.2650s) ===============================================
一切Okey,第二个迭代也已经结束:)
第三个迭代:Validate!
编辑app/model/product.rb文件:
class Product < ActiveRecord::Base
validates_presence_of :title, :description, :image_url
validates_numericality_of :price
validates_uniqueness_of :title
validates_format_of :image_url,
:with => %r{\.(gif|jpg|png)$}i,
:message => "must be a URL for a GIF, JPG, or PNG image"
protected
def validate
errors.add(:price, "should be at least 0.01") if price.nil? || price < 0.01
end
end
第四个迭代:Prettier Listings
创建静态的scaffold如下:
D:\IDE\rails-exampe\depot>ruby script/generate scaffold product admin
exists app/controllers/
exists app/helpers/
exists app/views/admin
exists app/views/layouts/
exists test/functional/
dependency model
exists app/models/
exists test/unit/
exists test/fixtures/
skip app/models/product.rb
identical test/unit/product_test.rb
identical test/fixtures/products.yml
create app/views/admin/_form.rhtml
create app/views/admin/list.rhtml
create app/views/admin/show.rhtml
create app/views/admin/new.rhtml
create app/views/admin/edit.rhtml
overwrite app/controllers/admin_controller.rb? [Ynaqd] y
force app/controllers/admin_controller.rb
overwrite test/functional/admin_controller_test.rb? [Ynaqd] y
force test/functional/admin_controller_test.rb
identical app/helpers/admin_helper.rb
overwrite app/views/layouts/admin.rhtml? [Ynaqd] y
force app/views/layouts/admin.rhtml
create public/stylesheets/scaffold.css
定制list.rhtml:
<div id="product-list">
<h1>Product Listing</h1>
<table cellpadding="5" cellspacing="0">
<% for product in @products %>
<tr valign="top" class="<%= cycle('list-line-odd', 'list-line-even') %>">
<td>
<img class="list-image" src="<%= product.image_url %>"/>
</td>
<td width="60%">
<span class="list-title"><%= h(product.title) %></span><br />
<%= h(truncate(product.description, 80)) %>
</td>
<td class="list-actions">
<%= link_to 'Show', :action => 'show', :id => product %><br/>
<%= link_to 'Edit', :action => 'edit', :id => product %><br/>
<%= link_to 'Destroy', { :action => 'destroy', :id => product },
:confirm => "Are you sure?",
:method => :post %>
</td>
</tr>
<% end %>
</table>
</div>
<%= if @product_pages.current.previous
link_to("Previous page", { :page => @product_pages.current.previous })
end
%>
<%= if @product_pages.current.next
link_to("Next page", { :page => @product_pages.current.next })
end
%>
<br />
<%= link_to 'New product', :action => 'new' %>
增加测试数据:
D:\IDE\rails-exampe\depot>ruby script/generate migration add_test_data
exists db/migrate
create db/migrate/003_add_test_data.rb
编辑db/migrate/003_add_test_data.rb:
class AddTestData < ActiveRecord::Migration
def self.up
Product.delete_all
Product.create(:title => 'Pragmatic Version Control',
:description =>
%{<p>
This book is a recipe-based approach to using Subversion that will
get you up and running quickly--and correctly. All projects need
version control: it's a foundational piece of any project's
infrastructure. Yet half of all project teams in the U.S. don't use
any version control at all. Many others don't use it well, and end
up experiencing time-consuming problems.
</p>},
:image_url => '/images/svn.jpg',
:price => 28.50)
end
def self.down
Product.delete_all
end
end
安装测试数据:
D:\IDE\rails-exampe\depot>rake db:migrate
输出:
D:0:Warning: require_gem is obsolete. Use gem instead.
(in D:/IDE/rails-exampe/depot)
== AddTestData: migrating =====================================================
== AddTestData: migrated (0.2030s) ============================================
编辑Layouts:app/views/layouts/admin.rhtml
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>Admin: <%= controller.action_name %></title>
<%= stylesheet_link_tag 'scaffold', 'depot' %>
</head>
<body>
<p style="color: green"><%= flash[:notice] %></p>
<%= yield :layout %>
</body>
</html>
编辑:app/views/admin/list.rhtml
<div id="product-list">
<h1>Product Listing</h1>
<table cellpadding="5" cellspacing="0">
<% for product in @products %>
<tr valign="top" class="<%= cycle('list-line-odd', 'list-line-even') %>">
<td>
<img class="list-image" src="<%= product.image_url %>"/>
</td>
<td width="60%">
<span class="list-title"><%= h(product.title) %></span><br />
<%= h(truncate(product.description, 80)) %>
</td>
<td class="list-actions">
<%= link_to 'Show', :action => 'show', :id => product %><br/>
<%= link_to 'Edit', :action => 'edit', :id => product %><br/>
<%= link_to 'Destroy', { :action => 'destroy', :id => product },
:confirm => "Are you sure?",
:method => :post %>
</td>
</tr>
<% end %>
</table>
</div>
<%= if @product_pages.current.previous
link_to("Previous page", { :page => @product_pages.current.previous })
end
%>
<%= if @product_pages.current.next
link_to("Next page", { :page => @product_pages.current.next })
end
%>
<br />
<%= link_to 'New product', :action => 'new' %>
参考:
http://www.rubyonrails.org/down
书籍《Agile Web Development with Rails》2nd Edition
另,JSR 315: Java Servlet 3.0 Specification under review at JCP:http://jcp.org/en/jsr/detail?id=315可以看到Servlet 3.0的规范中要涉及到的一些东西。