Hi,
I guess as many people, I am very new to Rails. I used a book to
create a shopping cart and then modified the code to try and fit it to
my project’s requirements. I have been trying figure this out for the
last week and starting to get really discouraged about the prospects
of solving this. I know what needs to be done but I’m at a loss for
how to achieve it. So, I wanted to ask, for help. Please please
please.
Background:
I have the following classes: customer, product, cart, cart_items,
order, order_items
A customer needs to login to even see the “Add to cart” links – so
the same goes for viewing cart and checkout. (which is achieved).
Things I have trouble with:
- The sessions are stored in the db. Right now, customer session and
cart session are separate. I need to assoociate them together. So,
when a customer loggs out and a new customer logs in, they have
different carts. If the session can remember the cart items, if the
same customer logs in again, that would be great. The customer id will
also need to be stored in the orders tables as well. - I suddently have trouble even trying to add an item to the cart.
- I need to figure out a way to update the quantity of items
(products) in the cart. - And lastly, my checkout page doesn’t come up suddenly as well
Please can anyone have a look and help me solve this?
Any help will be so much appreciated,
Thanks,
Elle
MODELS
customer.rb:
class Customer < ActiveRecord::Base
has_many :orders,
:dependent => true,
:order => “created_at ASC”
has_many :carts
validates_length_of :name, :within => 3…40
validates_uniqueness_of :name
validates_length_of :password, :within => 4…40, :if
=> :password_required?
def open_orders
orders.find(:all, :conditions => “status = ‘open’”)
end
def orders_history
orders.find(:all, :conditions => “status = ‘closed’”)
end
def password=(value)
write_attribute(“password”, Digest::SHA1.hexdigest(value))
end
def self.authenticate(name,password)
find(:first, :conditions => [“name = ? and password = ?”,name,
Digest::SHA1.hexdigest(password)])
end
def self.orders
current_customer = Customer.find(param[:id])
orders = current_customer.orders
end
def self.carts
current_customer = Customer.find(param[:id])
orders = current_customer.carts
end
end
cart.rb:
class Cart < ActiveRecord::Base
has_many :cart_items
has_many :products, :through => :cart_items
belongs_to :customer
def total
cart_items.inject(0) {|sum, n| n.price * n.amount + sum}
end
def add(product_id)
items = cart_items.find_all_by_product_id(product_id)
product = Product.find(product_id)
if items.size < 1
ci = cart_items.create(:product_id => product_id,
:amount => 1,
:price => product.price)
else
ci = items.first
ci.update_attribute(:amount, ci.amount + 1)
end
ci
end
def remove(product_id)
ci = cart_items.find_by_product_id(product_id)
if ci.amount > 1
ci.update_attribute(:amount, ci.amount - 1)
else
CartItem.destroy(ci.id)
end
return ci
end
def update(product_id)
items = cart_items.find_all_by_product_id(product_id)
product = Product.find(product_id)
ci = cart_items
ci.update_attribute(:amount, ci.amount + 1)
end
end
CONTROLLER
cart_controller.rb:
class CartController < ApplicationController
before_filter :initialize_cart
before_filter :authorize, :except => [“login”]
def authorize
return true if @c
flash[:notice] = “To place your order please login”
redirect_to :controller => “catalog”
end
def login
# examine the form data for “name” and “password”
pw,name = params[:customer].values_at(*%w{password name})
# Retrieve the customer record for the name and store it in a
variable ‘c’
c = Customer.find_by_name(name)
# if such record exists, and it’s password matches the password
from the form
if c && Digest::SHA1.hexdigest(pw) == c.password
# start a session with the customer id
session[:customer] = c.id
@cart = Cart.create
session[:customer]
if @cart.products.empty?
redirect_to :controller => "catalog"
else
redirect_to :action => "view_cart"
end
else
# otherwise report an error
flash[:notice] = "Invalid Login"
redirect_to :controller => "catalog"
end
end
def logout
session[:customer] = nil
redirect_to :controller => “catalog”
end
def index
end
def add
product = Product.find(params[:id])
if request.post?
@item = @cart.add(params[:id])
flash[:notice] = “Added #{@item.product.title} to
cart.”
redirect_to :controller => “catalog”
else
render
end
end
def update
@product = Product.find(params[:id])
if request.post?
@item = @cart.update_attributes(params[:cart])
flash[:notice] = “Updated #{@item.product.title}'s
quantity.”
redirect_to :action => “view_cart” and return if @cart.save
else
render
end
end
def remove
@product = Product.find(params[:id])
if request.post?
@item = @cart.remove(params[:id])
flash[:notice] = “Removed #{@item.product.title}”
redirect_to :action => “view_cart”
else
render
end
end
def clear
if request.post?
@cart.cart_items.destroy_all
flash[:notice] = “Cleared the cart”
redirect_to :controller => “catalog”
else
render
end
end
def view_cart
@page_title = “Shopping Cart for #{@c.name}”
@order = Order.new
if @cart.empty?
flash[:notice] = “Your shopping cart is empty! Please add
something to it before proceeding to checkout.”
redirect_to :controller => ‘catalog’
end
end
def checkout
@page_title = “Checkout”
@order = Order.new(params[:order])
@order.customer_ip = request.remote_ip
@order.customer_id = @session[‘customer’]
populate_order
if @order.save
if @order.process
flash[:notice] = 'Your order has been submitted, and will be
processed immediately.’
session[:order_id] = @order.id
# Empty the cart
@cart.cart_items.destroy_all
redirect_to :action => ‘thank_you’
else
flash[:notice] = “Error while placing order.
‘#{@order.error_message}’”
render :action => ‘view_cart’
end
else
render :action => ‘view_cart’
end
end
def thank_you
@page_title = ‘Thank You!’
end
def populate_order
for cart_item in @cart.cart_items
order_item = OrderItem.new(
:product_id => cart_item.product_id,
:price => cart_item.price,
:amount => cart_item.amount
)
@order.order_items << order_item
end
end
end
VIEWS
partial for cart item: _item.rhtml:
checkout.rhtml:
<%= error_messages_for ‘order’ %>
Your order’s total is: <%=h @cart.total %>
Contact Information<%= text_field :order, :email %>
<p><label for="order_phone_number">Phone number</label></p>
<p><%= text_field :order, :phone_number %></p>
Shipping Address
First name
<%= text_field :order, :ship_to_first_name %>
<p><label for="order_ship_to_last_name">Last name</label></p>
<p><%= text_field :order, :ship_to_last_name %></p>
<p><label for="order_ship_to_address">Address</label></p>
<p><%= text_field :order, :ship_to_address %></p>
<p><label for="order_ship_to_city">City</label></p>
<p><%= text_field :order, :ship_to_city %></p>
<p><label for="order_ship_to_postal_code">Postal/Zip code</label></
p>
<%= text_field :order, :ship_to_postal_code %>
<p><label for="order_ship_to_country">Country</label></p>
<p>
<select name="order[ship_to_country]" id="order_ship_to_country">
<option value="US">United States</option>
<option value="CA">Canada</option>
</select>
</p>
<%= submit_tag "Place Order" %>