End chapter 8
authorNeil Smith <neil.git@njae.me.uk>
Wed, 11 Feb 2009 20:33:28 +0000 (20:33 +0000)
committerNeil Smith <neil.git@njae.me.uk>
Wed, 11 Feb 2009 20:33:28 +0000 (20:33 +0000)
app/controllers/application.rb
app/controllers/store_controller.rb
app/models/cart.rb [new file with mode: 0644]
app/models/cart_item.rb [new file with mode: 0644]
app/views/layouts/store.html.erb
app/views/store/add_to_cart.html.erb [new file with mode: 0644]
config/environment.rb
db/migrate/20090211134638_create_sessions.rb [new file with mode: 0644]
public/stylesheets/depot.css

index 8dfb326615c1fcb91584d95547e664b886173461..fea87e2d210d5e5dfe122bfcc526fb008889ab8c 100644 (file)
@@ -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
index 9973d078727c334fc06a948e5bfe6c7a86ff0a56..f0103268556578461452c8c2bfa7b834c71600eb 100644 (file)
@@ -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 (file)
index 0000000..0f1d52e
--- /dev/null
@@ -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 (file)
index 0000000..6924ed7
--- /dev/null
@@ -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
index 7bd5325d42555b9ebe672c2d333b1960c732ffba..77e86d9e23e08684c1cbb69f3c329f337ed50fd0 100644 (file)
         <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 (file)
index 0000000..64270c3
--- /dev/null
@@ -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 %>
index 3884979ce8b3ced0bed46cce5ff38474da6ac19d..e727c3208bcf7f7ba09784e19d1346ec0b8a5344 100644 (file)
@@ -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 (file)
index 0000000..4ccc353
--- /dev/null
@@ -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
index a35a5bd55144a5739c7d87397d9d232e8b5bc863..bf77b4bd521c747695f222b5aea7359032a8684d 100644 (file)
@@ -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 {