`
moqi1212
  • 浏览: 4223 次
  • 性别: Icon_minigender_2
  • 来自: Boston
最近访客 更多访客>>
社区版块
存档分类
最新评论

《Agile Web Development with Rails》读书笔记三

阅读更多
任务C:

1、创建sessions
运行rake db:sessions:create(在数据表中创建一个session表)
再运行 rake db:migrate(更新当前的数据库)
因为,Rails默认的是使用cookies来记录所有的事情,所以我们现在需要更改配置,来指向我们所定义的session,所以需要修改config/initializers目录下的session_store.rb文件,在里面添加(下面的内容是Rails2.3下的显示)
  # Use the database for sessions instead of the cookie-based defaultl,
  # whic shouldn’t be used to store highly confidential information
  # (create the session table with ‘rake db:sessions:create’)
  ActionController::Base.session_store = :active_record_store

2、Sessions and Browsers
修改app\controllers\application_controller.rb文件,在里面添加:
protect_from_forgery
在重启Rails的服务,看看出现了什么?
接着,在存储controller中创建一个find_cart方法。
       private
        def find_cart
             session[:cart] ||= Cart.new
        end
 
3、Creating a Cart
a、在app/models目录中创建一个cart.rb文件:
      class Cart
attr_reader :items
def initialize
@items = [ ]
end
def add_product(product)
@items << product
end
end
b、修改app/views/store/index.html.erb文件,在里面添加:
   <%= button_to "Add to Cart" , :action => 'add_to_cart', :id => product %>
c、在app/controllers中修改store_controller.rb文件,添加如下代码:
          def add_to_cart
              product = Product.find(params[:id])
@cart = find_cart
@cart.add_product(product)
end
此时,点击Add to Cart按钮,会出现Template is missing错误,表示在views中没有add_to_cart.erb文件
d、所以,我们在app/views/store目录中添加add_to_cart.html.erb文件:
       <h2>Your Pragmatic Cart</h2>
<ul>
<% for item in @cart.items %>
<li><%=h item.title %></li>
<% end %>
</ul>
刷新网页,我们会发现,同一个产品,我们点多少次就增加多少个,不会对已经增加过的产品做一个检验。
e、所以,继续创建一个更为聪明的cart
在app/models中创建一个cart_item.rb文件:
class CartItem
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
f、再次修改app/views/store/add_to_cart.html.erb文件:
       <h2>Your Pragmatic Cart</h2>
<ul>
<% for item in @cart.items %>
<li><%= item.quantity %> &times; <%=h item.title %></li>
<% end %>
</ul>
g、接着要清除以前的session内容
   rake db:sessions:clear
h、然后,我们需要将当前网页退回到目录清单的网页界面,然后刷新,这时再点击Add to Cart按钮,就可以看到变化了

4、错误处理
修改app/controllers中的store_controller.rb文件:
def add_to_cart
product = Product.find(params[:id])
@cart = find_cart
@cart.add_product(product)
rescue ActiveRecord::RecordNotFound
logger.error("Attempt to access invalid product #{params[:id]}" )
flash[:notice] = "Invalid product"
redirect_to :action => 'index'
end
这时,我们在地址栏中输入http://localhost:3000/store/add_to_cart/wibble,就看不到错误信息了。
但是如果我们输入http://localhost:3000/store/wibble仍然可以在目录清单网页中看到错误信息的显示。
然后,我们接着修改app/views/layouts/store.html.erb文件:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" >
<html>
<head>
<title>Pragprog Books Online Store</title>
<%= stylesheet_link_tag "depot" , :media => "all" %>
</head>
<body id="store">
<div id="banner">
<%= image_tag("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 -%>
<%= yield :layout %>
</div>
</div>
</body>
</html>
   最后,在public\stylesheets中修改depot.css文件,在里面添加:
   #notice {
border: 2px solid red;
padding: 1em;
margin-bottom: 2em;
background-color: #f0f0f0 ;
font: bold smaller sans-serif;
}

5、完成购物车
1)要执行empty cart函数的话,就得给购物车做一个超链接来执行store contreller里的empty_cart方法,这里使用button_to这个方法
于是,我们修改app/views/store/add_to_cart.html.erb文件:
      <h2>Your Pragmatic Cart</h2>
<ul>
<% for item in @cart.items %>
<li><%= item.quantity %> &times; <%=h item.title %></li>
<% end %>
</ul>
<%= button_to 'Empty cart', :action => 'empty_cart' %>
         #按钮名称为Empty cart,其动作是链接empty_cart方法
   2)接着,我们设置controller中的empty_cart方法:a、从session中移除cart(即cart置空)b、flash中给一个消息表示cart置空c、重新传送给index。所以,修改app/controllers/stort_contrlooer.rb
def empty_cart
session[:cart] = nil
flash[:notice] = "Your cart is currently empty"
redirect_to :action => 'index'
end
   这时,我们再点击网页上的Empty Cart按钮,我们回到catalog page,并且会有一个消息出现:Your cart is currently empty。
   3)优化刚才写的代码,因为在stroe_controller.rb文件中,add_to_cartf方法和empty_cart方法中都用到了flash和redirect,所以我们在这里可以和在一起写一个redirect_to_index方法来完成这些。于是,我们再次修改app/controllers/stort_contrlooer.rb文件:
    def add_to_cart
product = Product.find(params[:id])
@cart = find_cart
@cart.add_product(product)
rescue ActiveRecord::RecordNotFound
logger.error("Attempt to access invalid product #{params[:id]}" )
redirect_to_index("Invalid product" )
end
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
4)美化购物车的页面,在这里依然使用CSS,首先修改app/views/add_to_cart.html.erb文件:
<div class="cart-title">Your Cart</div>
<table>
<% for item in @cart.items %>
<tr>
<td><%= item.quantity %>&times;</td>
<td><%=h item.title %></td>
<td class="item-price"><%= number_to_currency(item.price) %></td>
</tr>
<% end %>
<tr class="total-line">
<td colspan="2">Total</td>
<td class="total-cell"><%= number_to_currency(@cart.total_price) %></td>
</tr>
</table>
<%= button_to "Empty cart" , :action => :empty_cart %>
接着,我们需要在Cart model中增加一个求取所选货物的总价的方法,所以我们在app/models/cart.rb文件总增加:
def total_price
@items.sum { |item| item.price }
End
然后,在修改depot.css文件:public/stylesheets/depot.css
/* Styles for the cart in the main page */
.cart-title {
font: 120% bold;
}
.item-price, .total-line {
text-align: right;
}
.total-line .total-cell {
font-weight: bold;
border-top: 1px solid #595 ;
}
至此,就完成了cart的建立。
分享到:
评论
2 楼 shatler 2010-03-24  
晕 写错变量名了
1 楼 shatler 2010-03-24  
<% for item in @cart.items %>
<li><%= item.quantity %> &times; <%=h item.title %></li>
<% end %>

我试着调试了一下你的程序 ,上代码出现无each方法定义,确实好像CartItem类中无定义,不过 你又定义@items为数组,ruby中好像Array中有each方法定义。我作为初学者,不了解,请麻烦指教一下。

相关推荐

Global site tag (gtag.js) - Google Analytics