40bae534662670583678b03fe419e3f5

I've a simple cart application. Cart has many items, which belong to Product. I don't want users to add sample product twice. Somehow the below code doesn't seem like the most efficient way to do it. Also, I think the best way to prevent that would be not show the "Add to Cart" link in views.

class ItemsController < ApplicationController
  def create
    @product = Product.find(params[:product_id])
    @item = Item.new(:cart => current_cart,
                     :product => @product,
                     :quantity => 1,
                     :unit_price => @product.price)
    a = []
    current_cart.items.each do |item|
      a << item.product_id unless a.include?(item.product_id)
    end

    if a.include?(@item.product_id)
      flash[:notice] = "Product already in cart"
    else
      @item.save
      flash[:notice] = "Product added successfully"
    end
    redirect_to current_cart_url
  end
end

Refactorings

No refactoring yet !

D41d8cd98f00b204e9800998ecf8427e

steved

August 15, 2010, August 15, 2010 00:19, permalink

No rating. Login to rate!
class ItemsController < ApplicationController

  def create
    if current_cart.add_product(params[:product])
      flash[:notice] = "Product added successfully"
    else
      flash[:notice] = "Product already in cart"
    end
    redirect_to current_cart_url
  end
  
end

class Cart < ActiveRecord::Base
  has_many :items
  
  def self.add_product(product_id)
    if have_product?(product_id)
      false
    else
      product = Product.find(params[:product_id])
      items.create({
        :product => product,
        :quantity => 1,
        :unit_price => product.price,
      })
    end
  end
  
  def self.have_product?(product_id)
    items.find_by_product_id(product_id)
  end
  
end

module ItemsHelper 
  
  def add_to_cart_link(product_id)
    if Cart.have_product?(product_id)
      "In Cart"
    else
      link_to("Add to Cart", ...)
    end
  end
  
end
A8d3f35baafdaea851914b17dae9e1fc

Adam

August 17, 2010, August 17, 2010 00:20, permalink

No rating. Login to rate!

Additionally, set your quantity to default to 1 so that you do not have to specify it each time.

class Item < ActiveRecord::Base
  belongs_to :cart  
  belongs_to :product
  
  before_create :set_unit_price
  validates_uniqueness_of :product_id, :scope => :cart_id
  
  protected
    def set_unit_price
      self.unit_price = product.unit_price
    end
end

class ItemsController < ApplicationController
  def create
    @item = current_cart.items.build(:product => Product.find(params[:product_id]))
    
    flash[:notice] = @item.save ? 'Product added successfully' : 'Product already in cart'
    redirect_to current_cart_url
  end
end

Your refactoring





Format Copy from initial code

or Cancel