上一节: Ruby on Rails实战–创建一个网上商店a
本节创建商店的前台模块, 也就是客户看到的页面.
1.创建前台Controller Store:depot> ruby script/generate controller store index
最后的index创建一个index Action,用作默认action
2.创建一个session,用来保存购物篮数据
depot> rake db:sessions:create
然后
depot> rake db:migrate
(users of Rails applications must have cookies enabled in their browsers.???)
在config/environment.rb中将
config.action_controller.session_store = :active_record_store
语句前的注解符#去除,启动数据库保存session功能
*使用depot> rake db:sessions:clear可以清空当前session内容
3.创建前台的Store的Controller
修改depot/app/controllers/store_controller.rb文件为
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
class StoreController < ApplicationController
def index
@products = Product.find_products_for_sale
end
#find_products_for_sale将在model里面定义,见下文
#下面是购物篮添加程序
def add_to_cart
begin
@product = Product.find(params[:id])
rescue
logger.error("Attempt to access invalid product #{params[:id]}")
redirect_to_index("Invalid product")
else
@cart = find_cart
@cart.add_product(@product)
end
end
#上面的begin…rescue…else…end用来处理错误
#当begin出错,即找不到当前ID的商品时进行rescue处理,以防止入侵或意外出错
#上面的logger.eeror用来记录错误log,对应log目录里的development.log文件
# @product = Product.find(params[:id])可以接 add_to_cart/1 样式传来的request.
#上面的redirect_to_index见下面代码
#上面的find_cart见下面代码
#add_product()代码见下面.
#下面是购物篮清空程序
def empty_cart
session[:cart] = nil
redirect_to_index("Your cart is currently empty")
end
private #开始定义局部代码
#一个高压缩处理了的错误信息显示代码
def redirect_to_index(msg)
flash[:notice] = msg #用来显示出错信息
redirect_to :action => :index
end
#flash[:notice] = msg #用来显示flash信息
#redirect_to :action => :index 可用来转移页面.
#使用session来保存购物篮数据
def find_cart
session[:cart] ||= Cart.new
end
end
#上面的||=语句用来创建检查session,如果存在则调出数据,如果不存在生成新session
#!!!好符号化的语言啊!!!日本人不太懂英语吧.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
4.创建model:
修改depot/app/models/product.rb文件为:
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
class Product < ActiveRecord::Base
def self.find_products_for_sale
find(:all, :order => "title")
end
#用 self.前缀,定义class method
#上面的find(:all, :order => "title")让程序列出所有商品,按标题排序
#以下为原来的效验代码….
end
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
手动创建一个depot/app/models/cart.rb, 作为购物篮的model,内容如下:
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
class Cart
include Reloadable #手动创建的model要加入这句,以后服务器才会自动刷新
#Whenever youcreatea non-database model, youneed toinclude a includeReloadable directive in the source.
attr_reader :items
def initialize #初始化method
@items = [] # @items = []来赋空集.
end
def add_product(product)
existing_product = @items.find {|item| item.product == product}
if existing_product #如果篮中已有商品,累加数量
existing_product.increment_quantity
else
@items << CartItem.new(product)
end
end
def total_price
@items.inject(0) { |sum, item| sum + item.price }
end
end
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
手动创建一个depot/app/models/cart_item.rb model,用来处理购物篮内的商品,内容如下:
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
class CartItem
include Reloadable #见上文
attr_reader :product, :quantity
def initialize(product)
@product = product
@quantity = 1
end
def increment_quantity
@quantity += 1
end
def title
@product.title
end
def price
@product.price * @quantity
end
end
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
5.创建View:
修改depot/app/views/store/index.rhtml文件为:
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<% for product in @products -%>
<div class="entry">
<img src="<%= product.image_url %>"/>
<h3><%= h(product.title) %></h3>
<%= product.description %>
<span class="price"><%= format_price(product.price) %></span>
<%= button_to "Add to Cart", :action => :add_to_cart, :id => product %>
</div>
<br />
<% end %>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
*上面的product.description为使描述带有HTML代码,没有使用h(),带有安全隐患.
*上面的format_price为一个helper,来用格式化整数形的价格.见下文.
*上面的button_to将生成一个按钮,链接到add_to_cart action,用于向购物篮添加商品,它将以post方向向add_to_cart action传送商品ID信息. (post比get好???)
(And a POST request is just the ticket when we want to do something like add an item to a cart.)
*button_to的作用实际上相应于生成如下代码:
<form method="post" action="/store/add_to_cart/1" class="button-to">
<input type="submit" value="Add to Cart" />
</form>
手动建立一个添加商品页面的view depot/app/views/store/add_to_cart.rhtml,文件内容如下:
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<div class="cart-title">Your Cart</div>
<table>
<% for cart_item in @cart.items %>
<tr>
<td><%= cart_item.quantity %> ×</td>
<td><%= h(cart_item.title) %></td>
<td class="item-price"><%= format_price(cart_item.price) %></td>
</tr>
<% end %>
<tr class="total-line">
<td colspan="2">Total</td>
<td class="total-cell"><%= format_price(@cart.total_price) %></td>
</tr>
</table>
<%= button_to "Empty cart", :action => :empty_cart %>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
* ×生成一个乘号.
6.增加format_price helper
修改depot/app/helpers/store_helper.rb文件为:
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
module StoreHelper
def format_price(amount)
dollars, cents = amount.divmod(100)
sprintf("$%d.%02d", dollars, cents)
end
end
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
*上面的divmod是一个内置方法. 用它将以分为单位的整数形价格分为元和分两部分.
7.给view添加一个模板
修改:depot/app/views/layouts/store.rhtml文件内容为:
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<html>
<head>
<title>Pragprog Books Online Store</title>
<%= stylesheet_link_tag "depot", :media => "all" %>
</head>
<body id="store">
<div id="banner">
<img src="/images/logo.png"/>
<%= @page_title || "Pragmatic Bookshelf" %>
</div>
<div id="columns">
<div id="side">
<a href="http://www….">Home</a><br />
<a href="http://www…./faq">Questions</a><br />
<a href="http://www…./news">News</a><br />
<a href="http://www…./contact">Contact</a><br />
</div>
<div id="main">
<!–下面的代码显示错误提示信息–>
<% if flash[:notice] -%>
<div id="notice"><%= flash[:notice] %></div>
<% end -%>
<!–下面的代码显示不同action的子view内容–>
<%= @content_for_layout %>
<!–其它的内容为共用模板–>
</div>
</div>
</body>
</html>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
*这个和controller同名的layout文件为view的默认模板.
*<%= @page_title || "Pragmatic Bookshelf" %> ???
到这里用户界面已经基本完成.
调试使用 http://localhost:3000/store/访问
下一节:Ruby on Rails实战–创建一个网上商店C小试Ajax
转载请注明: 转自船长日志, 本文链接地址: http://www.cslog.cn/Content/ruby_on_rails_e_shop_b/
smart man !
thank you very much !
It’s suitable for beginners.