End chapter 10
authorNeil Smith <neil.git@njae.me.uk>
Sat, 7 Mar 2009 00:20:39 +0000 (00:20 +0000)
committerNeil Smith <neil.git@njae.me.uk>
Sat, 7 Mar 2009 00:20:39 +0000 (00:20 +0000)
16 files changed:
app/controllers/store_controller.rb
app/models/line_item.rb
app/models/order.rb
app/views/layouts/line_items.html.erb [new file with mode: 0644]
app/views/layouts/orders.html.erb [new file with mode: 0644]
app/views/layouts/store.html.erb
app/views/store/_cart.html.erb
app/views/store/_checkout.html.erb [new file with mode: 0644]
app/views/store/add_to_cart.js.rjs
app/views/store/checkout.html.erb [new file with mode: 0644]
app/views/store/checkout.js.rjs [new file with mode: 0644]
app/views/store/index.html.erb
db/migrate/20090304153209_create_orders.rb
db/migrate/20090304153613_create_line_items.rb
db/schema.rb
public/stylesheets/depot.css

index 3b2e6b8d2284fb79abea10c62d764d4f9ad573ce..de9e160be607cd54c7522ee77ad512f3ffa2640c 100644 (file)
@@ -21,7 +21,33 @@ class StoreController < ApplicationController
     session[:cart] = nil
     redirect_to_index unless request.xhr?
   end
+
+  def checkout
+    @cart = find_cart
+    if @cart.items.empty?
+      redirect_to_index("Your cart is empty" )
+    else
+      @order = Order.new
+      respond_to do |format|
+        format.js if request.xhr?
+        format.html
+      end
+    end
+  end
+
+  def save_order
+    @cart = find_cart
+    @order = Order.new(params[:order])
+    @order.add_line_items_from_cart(@cart)
+    if @order.save
+      session[:cart] = nil
+      redirect_to_index("Thank you for your order")
+    else
+      render :action => 'checkout'
+    end
+  end
   
+
  private
  
   def find_cart
index 988324ce31782a3ecf6e441960390f484968b478..61161a02a87601a5cf550bf08fd26cb071d80c20 100644 (file)
@@ -1,2 +1,12 @@
 class LineItem < ActiveRecord::Base
+  belongs_to :order
+  belongs_to :product
+
+  def self.from_cart_item(cart_item)
+    li = self.new
+    li.product      = cart_item.product
+    li.quantity     = cart_item.quantity
+    li.total_price  = cart_item.price
+    li
+  end
 end
index 0bcb15832b5dac818b8b163a3bd33e4f8073042a..bea4da6c367ca64ffc28bd46b63ad68769677126 100644 (file)
@@ -1,2 +1,20 @@
 class Order < ActiveRecord::Base
+  has_many :line_items
+
+  PAYMENT_TYPES = [
+    ["Cheque",          "cheque"],
+    ["Credit card",     "cc"],
+    ["Purchase order",  "po"]
+  ]
+
+  validates_presence_of :name, :address, :email, :pay_type
+  validates_inclusion_of :pay_type, :in =>
+    PAYMENT_TYPES.map {|disp, value| value}
+
+  def add_line_items_from_cart(cart)
+    cart.items.each do |item|
+      li = LineItem.from_cart_item(item)
+      line_items << li
+    end
+  end
 end
diff --git a/app/views/layouts/line_items.html.erb b/app/views/layouts/line_items.html.erb
new file mode 100644 (file)
index 0000000..78d24cc
--- /dev/null
@@ -0,0 +1,17 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+       "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+  <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
+  <title>LineItems: <%= controller.action_name %></title>
+  <%= stylesheet_link_tag 'scaffold' %>
+</head>
+<body>
+
+<p style="color: green"><%= flash[:notice] %></p>
+
+<%= yield  %>
+
+</body>
+</html>
diff --git a/app/views/layouts/orders.html.erb b/app/views/layouts/orders.html.erb
new file mode 100644 (file)
index 0000000..ee970df
--- /dev/null
@@ -0,0 +1,17 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+       "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+  <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
+  <title>Orders: <%= controller.action_name %></title>
+  <%= stylesheet_link_tag 'scaffold' %>
+</head>
+<body>
+
+<p style="color: green"><%= flash[:notice] %></p>
+
+<%= yield  %>
+
+</body>
+</html>
index e55726c75cec4041ac9d9eb0a20a9578cea51abc..63c7dd919a1df2a531a3c8bec20615df861387bd 100644 (file)
@@ -17,7 +17,7 @@
         <% hidden_div_if(@cart.items.empty?, :id => "cart") do %>
             <%= render(:partial => "cart" , :object => @cart) %>
         <% end %>
-        <a href="http://www....">Home</a><br />
+        <a href="/">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 />
index cc84043d9180968f7431ab16e7be41546fa38ca0..43e9a162a543f653864065095d9697a81a3e5038 100644 (file)
@@ -8,6 +8,10 @@
   </tr>
 </table>
 
+<% form_remote_tag :url => {:action => 'checkout'} do %>
+    <%= submit_tag "Checkout" %>
+<% end %>
+
 <% form_remote_tag :url => {:action => 'empty_cart'} do %>
     <%= submit_tag "Empty cart" %>
 <% end %>
diff --git a/app/views/store/_checkout.html.erb b/app/views/store/_checkout.html.erb
new file mode 100644 (file)
index 0000000..f5cd24f
--- /dev/null
@@ -0,0 +1,29 @@
+<div class="depot-form">
+  <%= error_messages_for 'order' %>
+  <% form_for :order, :url => { :action => :save_order } do |form| %>
+    <fieldset>
+      <legend>Please Enter Your Details</legend>
+      <div>
+        <%= form.label :name, "Name:" %>
+        <%= form.text_field :name, :size => 40 %>
+      </div>
+      <div>
+        <%= form.label :address, "Address:" %>
+        <%= form.text_area :address, :rows => 3, :cols => 40 %>
+      </div>
+      <div>
+        <%= form.label :email, "E-Mail:" %>
+        <%= form.text_field :email, :size => 40 %>
+      </div>
+      <div>
+        <%= form.label :pay_type, "Pay by:" %>
+        <%=
+        form.select :pay_type,
+          Order::PAYMENT_TYPES,
+          :prompt => "Select a payment method"
+        %>
+      </div>
+      <%= submit_tag "Place Order" , :class => "submit" %>
+    </fieldset>
+  <% end %>
+</div>
\ No newline at end of file
index 2ef0a833f279499c3434e98c4a25bcd7d1f45294..25dc8ca8c5c9f19a91ae096251aada7c18c488dc 100644 (file)
@@ -1,3 +1,5 @@
+page.select("div#notice").each {|div| div.hide}
+
 page.replace_html("cart", :partial => 'cart', :object => @cart)
 
 page[:cart].visual_effect :blind_down if @cart.total_items == 1
@@ -5,3 +7,4 @@ page[:cart].visual_effect :blind_down if @cart.total_items == 1
 page[:current_item].visual_effect :highlight,
                                   :startcolor => "#88ff88" ,
                                   :endcolor => "#114411"
+
diff --git a/app/views/store/checkout.html.erb b/app/views/store/checkout.html.erb
new file mode 100644 (file)
index 0000000..e41398d
--- /dev/null
@@ -0,0 +1 @@
+<%= render(:partial => "checkout", :object => @order) %>
diff --git a/app/views/store/checkout.js.rjs b/app/views/store/checkout.js.rjs
new file mode 100644 (file)
index 0000000..d819e16
--- /dev/null
@@ -0,0 +1 @@
+page.replace_html("main_panel", :partial => "checkout", :object => @order)
index f3e7ebedff34db7d48abeaa01929ff076ef094ae..63c12da3a258b96303b2a1a59169baabab38cea0 100644 (file)
@@ -1,3 +1,4 @@
+<div id="main_panel">
 <h1>Neil's Whimsical Store Catalogue</h1>
 
 <% for product in @products -%>
@@ -15,3 +16,4 @@
     </div>
   </div>
 <% end %>
+</div>
index a0a15980830232d7ae7e8f46f552ec1ecc7974d7..3852118c80154da99121d231c372058159611534 100644 (file)
@@ -4,7 +4,7 @@ class CreateOrders < ActiveRecord::Migration
       t.string :name
       t.text :address
       t.string :email
-      t.string :pay_type
+      t.string :pay_type, :limit => 10
 
       t.timestamps
     end
index 6870a05a03e9c333977d843f037b0683ab2dd149..fcd4625f33b61a965f9c0f14374d768f44b9f6bd 100644 (file)
@@ -1,13 +1,20 @@
 class CreateLineItems < ActiveRecord::Migration
   def self.up
     create_table :line_items do |t|
-      t.integer :product_id
-      t.integer :order_id
-      t.integer :quantity
-      t.decimal :total_price
+      t.integer :product_id,  :null => false
+      t.integer :order_id,    :null => false
+      t.integer :quantity,    :null => false
+      t.decimal :total_price, :null => false, :precision => 8, :scale => 2
 
       t.timestamps
     end
+
+    execute "alter table line_items add constraint fk_line_item_products
+                foreign key (product_id) references products(id)"
+
+    execute "alter table line_items add constraint fk_line_item_orders
+                foreign key (order_id) references orders(id)"
+    
   end
 
   def self.down
index d08e7634e294f0a2b0177146d693ca64884585cd..d017a0990895df72b442cbbe26907ad3b8f3ef84 100644 (file)
@@ -9,7 +9,28 @@
 #
 # It's strongly recommended to check this file into your version control system.
 
-ActiveRecord::Schema.define(:version => 20090226212307) do
+ActiveRecord::Schema.define(:version => 20090304153613) do
+
+  create_table "line_items", :force => true do |t|
+    t.integer  "product_id",                                :null => false
+    t.integer  "order_id",                                  :null => false
+    t.integer  "quantity",                                  :null => false
+    t.decimal  "total_price", :precision => 8, :scale => 2, :null => false
+    t.datetime "created_at"
+    t.datetime "updated_at"
+  end
+
+  add_index "line_items", ["order_id"], :name => "fk_line_item_orders"
+  add_index "line_items", ["product_id"], :name => "fk_line_item_products"
+
+  create_table "orders", :force => true do |t|
+    t.string   "name"
+    t.text     "address"
+    t.string   "email"
+    t.string   "pay_type",   :limit => 10
+    t.datetime "created_at"
+    t.datetime "updated_at"
+  end
 
   create_table "products", :force => true do |t|
     t.string   "title"
index bb4934d31524266461f4d27220b5dd00f21b1a06..5579185ff85be1c6f7e795b8dc96d2e969cc374d 100644 (file)
@@ -199,7 +199,41 @@ h1 {
 }
 /* END:cartside */
 
+/* START:form */
+/* Styles for order form */
 
+.depot-form fieldset {
+  background: #efe;
+}
+
+.depot-form legend {
+  color: #dfd;
+  background: #141;
+  font-family: sans-serif;
+  padding: 0.2em 1em;
+}
+
+.depot-form label {
+  width: 5em;
+  float: left;
+  text-align: right;
+  padding-top: 0.2em;
+  margin-right: 0.1em;
+  display: block;
+}
+
+.depot-form select, .depot-form textarea, .depot-form input {
+  margin-left: 0.5em;
+}
+
+.depot-form .submit {
+  margin-left: 4em;
+}
+
+.depot-form div {
+  margin: 0.5em 0;
+}
+/* END:form */
 
 /* The error box */