Question

I am trying to create a checkout with active merchant. I am using Ryan Bates Active merchant tutorial/ and the Agile web development book.

I get the following error, I'm not sure how to fix it to create a successful order. Any help is much appreciated.

NameError in OrdersController#create 

undefined local variable or method `line_items' for #<Order:0x007fcc467134b8>
Rails.root: /Users/macuser/rails_projects/listpro-a

Application Trace | Framework Trace | Full Trace
app/models/order.rb:33:in `block in add_line_items_from_cart'
app/models/order.rb:31:in `add_line_items_from_cart'
app/controllers/orders_controller.rb:33:in `create'

OrdersController

class OrdersController < ApplicationController

def index
   @orders = Order.paginate :page=>params[:page], :order=>'created_at desc',
   :per_page => 10
   respond_to do |format|
     format.html # index.html.erb
     format.xml { render :xml => @orders }
  end
end

def new
@cart = current_cart
@order_total = current_cart.total_price

if @cart.line_items.empty?
  redirect_to services_path, :notice => "Your cart is empty"
  return
end

@order = Order.new

respond_to do |format|
  format.html # new.html.erb
  format.xml { render :xml => @order }
end
end

def create
@order = current_cart.build_order(params[:order])
@order.ip_address = request.remote_ip
@order.add_line_items_from_cart(current_cart)
respond_to do |format|
  if @order.save
    if @order.purchase          
      Cart.destroy(session[:cart_id])
      session[:cart_id] = nil
      format.html { redirect_to(redirect_to new_listing_path, :notice => 'Thank you for your order.') }
      format.xml { render :xml => @order, :status => :created, :location => @order }
    else
      render :action => "failure"
    end

  else
    format.html { render :action => "new" }
    format.xml { render :xml => @order.errors,
    :status => :unprocessable_entity }
  end
end
end  
end

Order Model

class Order < ActiveRecord::Base
  # PAYMENT_TYPES = [ "visa", "master card", "Amex", "Discover" ] Controll the payment     options via Model
  attr_accessible :card_expires_on, :card_type, :first_name, :ip_address, :last_name,    :cart_id, :card_number, :card_verification



 # belongs_to :user
 # belongs_to :house
   belongs_to :cart

 has_many :transactions, :class_name => "OrderTransaction"
 # has_many :line_items, :dependent => :destroy

 attr_accessor :card_number, :card_verification

 validate :validate_card, :on => :create

 def purchase
    response = GATEWAY.purchase(price_in_cents, credit_card)
    transactions.create!(:action => "purchase", :amount => price_in_cents, :response => response)
    # cart.update_attribute(:purchased_at, Time.now) if response.success?
    response.success?
  end

  # Issue is here
  def price_in_cents 
  (cart.total_price*100).round
  end

  def add_line_items_from_cart(cart)
     cart.line_items.each do |item|
     item.cart_id = nil
     line_items << item
  end
 end


  private

  def validate_card
    unless credit_card.valid?
      credit_card.errors.full_messages.each do |message|
        errors[:base] << message
      end
    end
   end

  def credit_card
    @credit_card ||= ActiveMerchant::Billing::CreditCard.new(
     :type               => card_type,
      :number             => card_number,
      :verification_value => card_verification,
      :month              => card_expires_on.month,
      :year               => card_expires_on.year,
      :first_name         => first_name,
      :last_name          => last_name

     )
   end
 end

Carts Model

class Cart < ActiveRecord::Base
  attr_accessible :purchased_at, :house_id, :user_id
  has_many :line_items # , :dependent => :destroy
  has_one :order
  # has_many :services, :through => :line_items
  # belongs_to :user


  def total_price
    # convert to array so it doesn't try to do sum on database directly
    line_items.to_a.sum { |line_item| line_item.total_price }
  end

  def add_service(service_id)
   current_item = line_items.find_by_service_id(service_id)

   if current_item

          # render current cart with flash " you already have this service"
       else 
         current_item = line_items.build(:service_id => service_id)
       end
     current_item
   end
end

Applications Controller

class ApplicationController < ActionController::Base
  protect_from_forgery

  rescue_from CanCan::AccessDenied do |exception|
    redirect_to root_path, :alert => exception.message
  end


  helper :all


  private

  def current_cart

    Cart.find(session[:cart_id])
    rescue ActiveRecord::RecordNotFound
    cart = Cart.create(:user_id => current_user.id)
    session[:cart_id] = cart.id
    cart
  end

DB SCHEMA

create_table "carts", :force => true do |t|
    t.integer  "user_id"
    t.datetime "purchased_at"
    t.datetime "created_at",   :null => false
    t.datetime "updated_at",   :null => false
  end

create_table "order_transactions", :force => true do |t|
    t.integer  "order_id"
    t.string   "action"
    t.integer  "amount"
    t.boolean  "success"
    t.string   "authorization"
    t.string   "message"
    t.text     "params"
    t.datetime "created_at",    :null => false
    t.datetime "updated_at",    :null => false
  end


create_table "orders", :force => true do |t|
    t.integer  "cart_id"
    t.string   "ip_address"
    t.string   "first_name"
    t.string   "last_name"
    t.string   "card_type"
    t.integer  "house_id"
    t.integer  "user_id"
    t.date     "card_expires_on"
    t.datetime "created_at",      :null => false
    t.datetime "updated_at",      :null => false
  end
Was it helpful?

Solution

This line is commented out in your Order model:

# has_many :line_items, :dependent => :destroy

Since you are using this association in the add_line_items_from_cart method, it doesn't work if you comment it out.

OTHER TIPS

The error stems from:

 line_items << item

You removed the has_many relationship in the Order class.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top