Agile Web Development with Rails 4E 学习笔记2
=========zqhxuyuan@gmail.com 2011.10=========
声明:本文根据英文电子版Rails3 4E 2011-03-29 重要的地方有中文注释.
采用Notepad++编辑(语言:YAML),发布在ItEye上可能看起来不是很美观.
PS:只是RoR新手(而且尼玛还在win7上编程,羡慕Mac..),如有错误,欢迎指正.
===========================================
Chapter 10. Task E. A Smarter Cart
5.1 相同购物项显示Product的数量:
> rails generate migration add_quantity_to_line_items quantity:integer
-> db/migrate/add_quantity_to_line_items.rb
class AddQuantityToLineItems < ActiveRecord::Migration
def self.up
add_column :line_items, :quantity, :integer, :default => 1
end
end
> rake db:migrate
create_table "line_items"
t.integer "product_id"
t.integer "cart_id"
t.integer "quantity", :default => 1
end
给购物项LineItems添加字段quantity,检查购物车中的购物项是否存在将要添加的Product
-> app/models/cart.rb
def add_product(product_id)
current_item = line_items.find_by_product_id(product_id)
if current_item
current_item.quantity += 1
else
current_item = line_items.build(:product_id => product_id)
end
current_item
end
-> app/controllers/line_items_controller.rb
def create
@cart = current_cart
product = Product.find(params[:product_id])
#@line_item = @cart.line_items.build(:product => product)
@line_item = @cart.add_product(product.id)
end
-> app/views/carts/show.html.erb
<%= item.quantity %> × <%= item.product.title %>
重新访问http://localhost:3000 添加Product到购物车中.如果添加的是相同的Product,
则购物车中显示的是数量,而不是一个一个Product列举出来.比如:http://localhost:3000/carts/5
Your Pragmatic Cart
2 × Programming Ruby 1.9
4 × Debug It!
5.2
数据库提交和回滚操作:
当访问http://localhost:3000/carts/2时 因为cart_id=2的那些操作在5.1之前,所以显示是还是一个一个列举Product.
为了使所有的购物车都运用到5.1中的操作.即看到的都是:如果有相同Product,则显示相同的数量.
我们要做的是migrate the data:
> rails generate migration combine_items_in_cart
-> db/migrate/combine_items_in_cart.rb
def self.up
# replace multiple items for a single product in a cart with a single item
Cart.all.each do |cart|
# count the number of each product in the cart
sums = cart.line_items.group(:product_id).sum(:quantity)
sums.each do |product_id, quantity|
if quantity > 1
# remove individual items
cart.line_items.where(:product_id=>product_id).delete_all
# replace with a single item
cart.line_items.create(:product_id=>product_id, :quantity=>quantity)
end
end
end
end
> rake db:migrate
访问http://localhost:3000/carts/2 这时cart_id=2的购物车中显示的不再是一个一个相同的Product,也是有数量的.
def self.down
# split items with quantity>1 into multiple items
LineItem.where("quantity>1").each do |line_item|
# add individual items
line_item.quantity.times do
LineItem.create :cart_id=>line_item.cart_id, :product_id=>line_item.product_id, :quantity=>1
end
# remove original item
line_item.destroy
end
end
> rake db:rollback
在此访问http://localhost:3000/carts/2 则又回到5.1之前的显示.
5.3 错误处理及flash内容显示:
当访问如http://localhost:3000/carts/wibble会报错ActiveRecord::RecordNotFound in CartsController#show
Rails处理错误一种方便的方式是使用flash这种类似hash的结构.(下面的:notice => 'Invalid cart'即hash结构)
A hash is a bucket in which you can store stuff as you process a request.
The contents of the hash are available to the next request in this session before being deleted automatically.
flash中的内容在同一个Session中被删除之前 可以被下一个URL请求所获取.flash常用于错误信息收集.
比如访问/carts/wibble,show方法检测到传递一个无效的cartid,flash可以存储错误消息,
在重定向到index页面时(Controller的Action:index,对应view的index.html.erb),
可以提起出错误消息显示出来.这里next request即show的下一个请求index可以获取到放置到show里的flash的内容.
The flash information is accessible within the views by using the flash accessor method.
-> app/controllers/carts_controller.rb
def show
begin
@cart = Cart.find(params[:id])
rescue ActiveRecord::RecordNotFound
logger.error "Attempt to access invalid cart #{params[:id]}"
redirect_to store_url, :notice => 'Invalid cart'
else
#...
end
end
-> views/store/index.html.erb
<% if notice %>
<p id="notice"><%= notice %></p>
<% end %>
CartsController#show 中放置在flash的错误消息:notice => 'Invalid cart'
重定向到store_url即StoreController#index,在views/store/index.html.erb中可以取出来:<%= notice %>
为什么不使用Controller中存在的实例变量来存储错误消息.
因为在我们的应用中(show方法里),使用的是浏览器重定向.重定向:浏览器发送一个新的请求给我们的应用即
StoreController#index.当我们接收另外的这个请求时,之前的请求中存在的实例变量(CartController#show)都会消失.
而flash中的数据是存储在Session中的.在多次不同的请求中数据是都可以获取到的.
5.4 清空购物车:
deleting their own (current) cart,and to remove the cart from the session.
-> app/views/carts/show.html.erb
<%= button_to 'Empty cart', @cart, :method => :delete, :confirm => 'Are you sure?' %>
-> app/controllers/carts_controller.rb
def destroy
@cart = current_cart
@cart.destroy
session[:cart_id] = nil
respond_to do |format|
format.html { redirect_to(store_url, :notice => 'Your cart is currently empty') }
format.xml { head :ok }
end
end
测试时,由于测试环境是木有Session的,所以初始时我们把当前的购物车
(cart_id:@cart.id)放到Session中来模拟Controller中的current_cart
-> test/functional/carts_controller_test.rb
test "should destroy cart" do
assert_difference('Cart.count', -1) do
session[:cart_id] = @cart.id
delete :destroy, :id => @cart.to_param
end
assert_redirected_to store_path
end
remove the flash message that is automatically generated when a line item is added.
-> app/controllers/line_items_controller.rb
format.html { redirect_to(@line_item.cart) }
5.5 显示价格信息:
add a method to both the LineItem and Cart models that returns
the total price for the individual line item and entire cart
-> app/views/carts/show.html.erb
<% @cart.line_items.each do |item| %>
<%= number_to_currency(item.total_price) %>
<% end %>
<%= number_to_currency(@cart.total_price) %>
-> app/models/line_item.rb
class LineItem < ActiveRecord::Base
belongs_to :product
belongs_to :cart
def total_price
product.price * quantity
end
end
-> app/models/cart.rb
class Cart < ActiveRecord::Base
has_many :line_items, :dependent => :destroy
def total_price
line_items.to_a.sum {|item| item.total_price}
end
end
关于Model中方法访问变量:LineItem belongs_to的内容相当于定义了一个变量.
不同的是belongs_to定义的内容是Symbol类型,而在方法中使用的应该是去掉Symbol之前的:的变量.
比如belongs_to :product,则total_price方法中可以访问product.
*quantity.因为在5.1中add_quantity_to_line_items给line_items添加了一个quantity字段.
相当于给Model:LineItem添加了一个属性.所以在Model对象里是可以访问自己的属性的.
也就是说Model方法里可以访问的属性包括:
数据库定义的字段=>对应Model添加的属性.
Model中定义的依赖关系: belongs_to has_many 定义的Symbol对应的变量(去掉Symbol前的冒号)
分享到:
相关推荐
在《Agile Web Development with Rails》中,读者可以学习到如何运用敏捷方法来规划项目,实施增量式开发,并通过频繁的反馈来提高产品质量。 Ruby on Rails(简称Rails)是一个基于Ruby语言的开源Web开发框架,它...
Ruby on Rails helps you produce high-quality, beautiful-looking web applications quickly. You concentrate on creating the application, and Rails takes care of the details., Tens of thousands of ...
《Agile Web Development with Rails》(敏捷Web开发:Ruby on Rails)这本书,作为Rails开发新手的教材,强调了敏捷开发方法,并以其帮助开发者建立起一个实用的Web应用。从给出的文件信息来看,这本书正在编写过程...
Agile Web Development with Rails 1-14节_ppt(老师发的修正版)
agile web development with rails 5(英文电子书).............................................................................................................................................................
《敏捷Web开发与Rails》是一本深度探讨如何利用Ruby on Rails框架进行敏捷Web开发的指导书籍,由Dave Thomas、David Heinemeier Hansson等多位在Rails社区有着深厚贡献的作者共同编写。本书不仅覆盖了Rails的基本...
本书《敏捷Web开发与Rails》第三版是基于Rails 2编写的。截至本书印刷时,当前可用的Rails Gem版本为2.1。书中所包含的所有代码均已在该版本上进行了测试。 在本书撰写初期,其内容与第二版相同,后者涵盖了Rails ...
《敏捷Web开发与Rails:程序指南 第四版》是一本深度探讨使用Ruby on Rails框架进行敏捷Web应用开发的专业书籍。本书旨在帮助开发者充分利用Rails 4的特性,提高开发效率,实现快速迭代和高质量的代码编写。 Rails是...
《敏捷Web开发与Rails》第四版是一本专为软件开发者设计的权威指南,全面涵盖了使用Ruby on Rails框架进行敏捷Web应用开发的知识。Rails 3是该版本的重点,它引入了许多新特性和改进,使得开发过程更为高效且灵活。...
Agile Web Development with Rails, 2nd Edition <br>有两份PDF文件,大小分别是7.39MB和6.55MB <br>作者: Dave Thomas , David Heinemeier Hansson , Leon Breedt , Mike Clark , James Duncan Davidson ,...
在学习这两本书时,你可以从Pragmatic Programmer - Agile Web Development With Ruby On Rails_05.12.24.pdf和Pragmatic.Bookshelf.Agile.Web.Development.with.Rails.2nd.Edition.pdf中获取详细教程。这些PDF文件...
《Pragmatic - Agile Web Development with Rails》是Ruby on Rails框架的经典教材,旨在引导初学者高效地学习敏捷Web开发。这本书的第三版于2009年发布,它结合了Pragmatic Programmers的实用主义理念与Ruby on ...
### Agile Web Development with Rails for Rails 3.2 #### 核心知识点概览 - **Rails 3.2概述** - **敏捷开发方法论** - **Model-View-Controller (MVC) 模式** - **Ruby on Rails基础与高级特性** - **面向对象...
Agile Web Development with Rails 4th(正式版).pdf
### Agile Web Development with Rails 第四版 #### 书籍概述与价值 《Agile Web Development with Rails》第四版是一本经典的Rails开发指南,旨在为开发者提供一套全面、实用且高效的敏捷开发方法论。本书由Sam ...