From: Neil Smith <neil.git@njae.me.uk>
Date: Wed, 11 Feb 2009 20:33:28 +0000 (+0000)
Subject: End chapter 8
X-Git-Url: https://git.njae.me.uk/?a=commitdiff_plain;h=c611b802645df9f0b490550d8c352fd24eb6ec5b;p=depot.git

End chapter 8
---

diff --git a/app/controllers/application.rb b/app/controllers/application.rb
index 8dfb326..fea87e2 100644
--- a/app/controllers/application.rb
+++ b/app/controllers/application.rb
@@ -6,7 +6,7 @@ class ApplicationController < ActionController::Base
 
   # See ActionController::RequestForgeryProtection for details
   # Uncomment the :secret if you're not using the cookie session store
-  protect_from_forgery # :secret => 'd7e9713fb540572dab37a045152d442a'
+  protect_from_forgery :secret => 'd7e9713fb540572dab37a045152d442a'
   
   # See ActionController::Base for details 
   # Uncomment this to filter the contents of submitted sensitive data parameters
diff --git a/app/controllers/store_controller.rb b/app/controllers/store_controller.rb
index 9973d07..f010326 100644
--- a/app/controllers/store_controller.rb
+++ b/app/controllers/store_controller.rb
@@ -3,4 +3,29 @@ class StoreController < ApplicationController
     @products = Product.find_products_for_sale
   end
 
+  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 has been emptied')
+  end
+  
+ private
+ 
+  def find_cart
+    session[:cart] ||= Cart.new
+  end
+
+  def redirect_to_index(msg)
+    flash[:notice] = msg
+    redirect_to :action => 'index'
+  end
+  
 end
diff --git a/app/models/cart.rb b/app/models/cart.rb
new file mode 100644
index 0000000..0f1d52e
--- /dev/null
+++ b/app/models/cart.rb
@@ -0,0 +1,21 @@
+class Cart
+  attr_reader :items
+  
+  def initialize
+    @items = []
+  end
+  
+  def add_product(product)
+    current_item = @items.find {|item| item.product == product}
+    if current_item
+      current_item.increment_quantity
+    else
+      @items << CartItem.new(product)
+    end
+  end
+  
+  def total_price
+    @items.sum {|item| item.price}
+  end
+  
+end
diff --git a/app/models/cart_item.rb b/app/models/cart_item.rb
new file mode 100644
index 0000000..6924ed7
--- /dev/null
+++ b/app/models/cart_item.rb
@@ -0,0 +1,21 @@
+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
diff --git a/app/views/layouts/store.html.erb b/app/views/layouts/store.html.erb
index 7bd5325..77e86d9 100644
--- a/app/views/layouts/store.html.erb
+++ b/app/views/layouts/store.html.erb
@@ -19,6 +19,10 @@
         <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>
diff --git a/app/views/store/add_to_cart.html.erb b/app/views/store/add_to_cart.html.erb
new file mode 100644
index 0000000..64270c3
--- /dev/null
+++ b/app/views/store/add_to_cart.html.erb
@@ -0,0 +1,18 @@
+<h2>Your Whimsical Cart</h2>
+
+<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, :unit => "£") %></td>
+        </tr>
+    <% end %>
+        <tr class="total-line">
+            <td colspan="2">Total</td>
+            <td class="total-cell"><%= number_to_currency(@cart.total_price, :unit => "£") %></td>
+        </tr>
+    </table>
+
+<%= button_to 'Empty cart', :action => :empty_cart %>
diff --git a/config/environment.rb b/config/environment.rb
index 3884979..e727c32 100644
--- a/config/environment.rb
+++ b/config/environment.rb
@@ -62,7 +62,7 @@ Rails::Initializer.run do |config|
   # Use the database for sessions instead of the cookie-based default,
   # which shouldn't be used to store highly confidential information
   # (create the session table with "rake db:sessions:create")
-  # config.action_controller.session_store = :active_record_store
+  config.action_controller.session_store = :active_record_store
 
   # Use SQL instead of Active Record's schema dumper when creating the test database.
   # This is necessary if your schema can't be completely dumped by the schema dumper,
diff --git a/db/migrate/20090211134638_create_sessions.rb b/db/migrate/20090211134638_create_sessions.rb
new file mode 100644
index 0000000..4ccc353
--- /dev/null
+++ b/db/migrate/20090211134638_create_sessions.rb
@@ -0,0 +1,16 @@
+class CreateSessions < ActiveRecord::Migration
+  def self.up
+    create_table :sessions do |t|
+      t.string :session_id, :null => false
+      t.text :data
+      t.timestamps
+    end
+
+    add_index :sessions, :session_id
+    add_index :sessions, :updated_at
+  end
+
+  def self.down
+    drop_table :sessions
+  end
+end
diff --git a/public/stylesheets/depot.css b/public/stylesheets/depot.css
index a35a5bd..bf77b4b 100644
--- a/public/stylesheets/depot.css
+++ b/public/stylesheets/depot.css
@@ -1,5 +1,17 @@
 /* Global styles */
 
+/* Global styles */
+
+/* START:notice */
+#notice {
+  border: 2px solid red;
+  padding: 1em;
+  margin-bottom: 2em;
+  background-color: #f0f0f0;
+  font: bold smaller sans-serif;
+}
+/* END:notice */
+
 h1 {
         font:  150% sans-serif;
         color: #226;
@@ -155,6 +167,24 @@ h1 {
 }
 
 
+/* START:cartmain */
+/* 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;
+}
+/* END:cartmain */
+
+
 /* The error box */
 
 .fieldWithErrors {