Agile Web Development with Rails 翻译(十六)
8.5 循环 C3: 完成购物车
让我们开始处理购物车显示上的空购物车连接。我们知道我们必须在store “控制器”内实现一个empty_cart()方法。让我们将它的职责委派给Cart类。
2006年4月17日更新
def empty_cart
find_cart.empty!
flash[:notice] = 'Your cart is now empty'
redirect_to(:action => 'index')
end
在cart内,我们实现了empty!()方法。
def empty!
@items = []
@total_price = 0.0
end
现在当我们单击空购物车连接时,我们会回到分类目录页,并显示一个友好提示消息。
但是,还有个问题。让我们回过头看看我们的代码,我们引入了两个重复的部分。
首先,store “控制器”内,我们现在三个地方放置了一个给flash的消息以及重定向到索引页。听起来我们应该抽取公共部分的代码放到一个方法内,所以让们实现redirect_to_index()方法,并修改add_to_cart(),display_cart(),和empty_cart()方法来使用它。
def add_to_cart
product = Product.find(params[:id])
@cart = find_cart
@cart.add_product(product)
redirect_to(:action => 'display_cart')
rescue
logger.error("Attempt to access invalid product #{params[:id]}")
redirect_to_index('Invalid product')
end
def display_cart
@cart = find_cart
@items = @cart.items
if @items.empty?
redirect_to_index("Your cart is currently empty")
end
end
def empty_cart
@cart = find_cart
@cart.empty!
redirect_to_index('Your cart is now empty')
end
private
def redirect_to_index(msg = nil)
flash[:notice] = msg if msg
redirect_to(:action => 'index')
end
第二个重复的部分在cart “模型”内,是两个构造器和empty!方法完成同样的事情。这很容易修补—我们将在构造器内调用empty!()的方法。
def initialize
empty!
end
def empty!
@items = []
@total_price = 0.0
end
“帮助方法”(Helper)
这个阶段的第二个任务是整理购物车内显示的美元符号。原来是59.9,我们应该显示$59.90。
现在我们知道要做什么了。我们可以放置sprintf()方法在“视图”中。
<td align="right">
<%= sprintf("$% 0.2f", item.unit_price) %>
</td>
但是在做之前,让我们先想想。我们必须为我们显示每个美元符号都要这么做。这是一种重复。如果客户后来让我们在三位数字中插入一个逗号,或者在一个圆括号内表示负数会怎么样呢?最的办法是抽取货币格式化到一个单独方法内,以便我们只在这一处进行更改。在写方法之前,我们必须知道该写到哪里才合适。
幸运了,Rails有个答案—它让我定义了“帮助方法”。这个“帮助方法”是一个“模块”内的简单方法,它自动被包含到你的“视图”中。你在app/helpers目录内定义helper文件。名为xyz_helper.rb的文件定义了对由xyz “控制器”调用的“视图”有效的方法。如果你在文件app/helpers/application_helper.rb中定义了“帮助方法”,这些方法将在所有“视图”中有效。像显示美元合计似乎是个平常的事情,让我们添加方法到那个文件中。
# The methods added to this helper will be available
# to all templates in the application.
module ApplicationHelper
def fmt_dollars(amt)
sprintf("$% 0.2f", amt)
end
end
我们将更新购物车显示页面的“视图“使用这个新方法。
<%
for item in @items
product = item.product
-%>
<tr>
<td><%= item.quantity %></td>
<td><%= h(product.title) %></td>
<td align="right"><%= fmt_dollars(item.unit_price) %></td>
<td align="right"><%= fmt_dollars(item.unit_price * item.quantity) %></td>
</tr>
<% end %>
<tr>
<td colspan="3" align="right"><strong>Total:</strong></td>
<td id="totalcell"><%= fmt_dollars(@cart.total_price) %></td>
</tr>
现在,当我显示购物车时,美元合计看起来格式化的不错。
现在是讨论的时间。这段时间我们写了这个例子应用程序,Rails发行到了1.0。后来很多有关数字的内置“帮助方法”被添加了进来。这些方法中的一个是number_to_currency(),它将代替我们刚刚写的fmt_dollars()方法。但是,如果我们修改本书使用这些新方法,我们将不能够显示给你如何写你自己的“帮助方法”。
最后是,在分类目录页面中(由index.rhtml模板创建的)我们使用sprintf()来格式化产品单价。现在我们有了更方便的货币格式化工具,我们也将使用它。我们不再显示它,因为这个修改太微不足道了。
我们刚才做了些什么
似乎忙了一天,但只做了一件事。我们添加了一个购物车给我们的商店,随后我们又使用了一些Rails的特征。
1、使用“会话”来存储状态。
2、使用belogs_to关联Rails的“模型”。
3、创建并整合并数据库“模型”。
4、使用flash来传递动作之间的错误。
5、用“帮助方法”移除重复代码。
6、使用logger来记录事件。
现在客户想看看结算功能。那是在下一章。