From c611b802645df9f0b490550d8c352fd24eb6ec5b Mon Sep 17 00:00:00 2001 From: Neil Smith Date: Wed, 11 Feb 2009 20:33:28 +0000 Subject: [PATCH] End chapter 8 --- app/controllers/application.rb | 2 +- app/controllers/store_controller.rb | 25 ++++++++++++++++ app/models/cart.rb | 21 ++++++++++++++ app/models/cart_item.rb | 21 ++++++++++++++ app/views/layouts/store.html.erb | 4 +++ app/views/store/add_to_cart.html.erb | 18 ++++++++++++ config/environment.rb | 2 +- db/migrate/20090211134638_create_sessions.rb | 16 +++++++++++ public/stylesheets/depot.css | 30 ++++++++++++++++++++ 9 files changed, 137 insertions(+), 2 deletions(-) create mode 100644 app/models/cart.rb create mode 100644 app/models/cart_item.rb create mode 100644 app/views/store/add_to_cart.html.erb create mode 100644 db/migrate/20090211134638_create_sessions.rb 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 @@ Contact
+ <% if flash[:notice] -%> +
<%= flash[:notice] %>
+ <% end -%> + <%= yield :layout %>
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 @@ +

Your Whimsical Cart

+ +
Your Cart
+ + <% for item in @cart.items %> + + + + + + <% end %> + + + + +
<%= item.quantity %>×<%=h item.title %><%= number_to_currency(item.price, :unit => "£") %>
Total<%= number_to_currency(@cart.total_price, :unit => "£") %>
+ +<%= 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 { -- 2.34.1