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
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
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
--- /dev/null
+<!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>
--- /dev/null
+<!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>
<% 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 />
</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 %>
--- /dev/null
+<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
+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
page[:current_item].visual_effect :highlight,
:startcolor => "#88ff88" ,
:endcolor => "#114411"
+
--- /dev/null
+<%= render(:partial => "checkout", :object => @order) %>
--- /dev/null
+page.replace_html("main_panel", :partial => "checkout", :object => @order)
+<div id="main_panel">
<h1>Neil's Whimsical Store Catalogue</h1>
<% for product in @products -%>
</div>
</div>
<% end %>
+</div>
t.string :name
t.text :address
t.string :email
- t.string :pay_type
+ t.string :pay_type, :limit => 10
t.timestamps
end
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
#
# 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"
}
/* 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 */