سؤال

I have an order form which accepts credit card information in a form. It doesn't seem to be working correctly because every time I enter test information and submit it just sends me back to the new action which means @order.save isn't working. I don't see why my order isnt saving.

Here is the server log:

Redirected to http://localhost:3000/orders/new
Completed 302 Found in 79ms (ActiveRecord: 65.8ms)
Started GET "/orders/new" for 127.0.0.1 at 2013-07-14 18:11:31 -0400
Processing by OrdersController#new as HTML
  Rendered orders/new.html.erb within layouts/application (99.5ms)
Completed 200 OK in 119ms (Views: 59.0ms | ActiveRecord: 46.5ms)
Started GET "/assets/dark.png" for 127.0.0.1 at 2013-07-14 18:11:31 -0400
Served asset /dark.png - 304 Not Modified (0ms)
Started GET "/assets/grey_wash_wall.png" for 127.0.0.1 at 2013-07-14 18:11:31 -0400
Served asset /grey_wash_wall.png - 304 Not Modified (0ms)
/home/winston/.rvm/gems/ruby-1.9.3-p125/gems/active_utils-1.0.5/lib/active_utils/common/validateable.rb:25:in `block in attributes='CreditCard#type is deprecated and will be removed from a future release of ActiveMerchant. Please use CreditCard#brand instead.
Started POST "/orders" for 127.0.0.1 at 2013-07-14 18:11:59 -0400
Processing by OrdersController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"N0pd/SJC2qwYkrFtCfZom7fVv/qBTe42p6gbiyyzbs8=", "order"=>{"first_name"=>"joseph", "last_name"=>"quad", "card_type"=>"visa", "card_number"=>"[FILTERED]", "card_verification"=>"[FILTERED]", "card_expires_on(1i)"=>"2013", "card_expires_on(2i)"=>"7", "card_expires_on(3i)"=>"1"}, "commit"=>"Complete Purchase"}
Redirected to http://localhost:3000/orders/new
Completed 302 Found in 103ms (ActiveRecord: 94.4ms)
Started GET "/orders/new" for 127.0.0.1 at 2013-07-14 18:11:59 -0400
Processing by OrdersController#new as HTML
  Rendered orders/new.html.erb within layouts/application (55.6ms)

form

  <%= form_for @order, validate: true do |f| %>
                          <% if @order.errors.any? %>
                          <ul>
                            <% @order.errors.full_messages.each do |msg| %>
                              <li><%= msg %></li>
                             <% end %>
                           </ul>
                       <% end %>
                       <ul class="unstyled">
                               <li>First name<br/><%= f.text_field :first_name %></li>
                               <li>Last name<br/><%= f.text_field :last_name %></li>
                               <li>Card type<br/><%= f.select :card_type, [["Visa", "visa"], ["MasterCard", "master"], ["American Express", "american_express"]], { prompt: 'Select Card Type' } %></li>
                               <li>Card number<br/><%= f.text_field :card_number %></li>
                               <li>Card Verification Value (CVV)<br/><%= f.text_field :card_verification, :class => "ordsize" %></li>
                               <li>Expiration<br/><%= f.date_select :card_expires_on, {:discard_day => true, :start_year => Date.today.year, :end_year => (Date.today.year+10), :add_month_numbers => true}, {:class => "datesize"} %></li>
                               <li><%= f.submit "Complete Purchase", :class=>"pull-right btn" %></p></li>
                       </ul>
                     <% end %>

order controller

class OrdersController < ApplicationController
before_filter :authenticate, :except => [:new]
def new
          @order = Order.new
          @cart = current_cart

  end

  def create
          @cart = current_cart
          @order = @cart.build_order(params[:order])
          @order.ip_address = request.remote_ip
          if @order.save
              if @order.purchase
                 unless current_cart.order_option.purchase_order.blank?
                     UserMailer.ordered("Successful w/ Purchase Order #", current_user, current_cart).deliver
                     UserMailer.confirmation(current_user, current_cart).deliver
                     render :action => "success"
                  else
                     UserMailer.ordered("Purchased", current_user, current_cart).deliver
                     UserMailer.confirmation(current_user, current_cart).deliver
                     render :action => "success"
                  end
              else
                 UserMailer.ordered("CCard Payment failed", current_user, current_cart).deliver
                 render :controller => "responses", :action => "failure"
              end
         else
              redirect_to :controller => "orders", :action => 'new'
         end
  end
  def purchase_order_summary
      @order = Order.new
      @cart = current_cart
  end

order model

class Order < ActiveRecord::Base
  attr_accessible :card_number, :card_verification, :card_expires_on, :card_type, :cart_id, :first_name, :ip_address, :last_name
  belongs_to :cart
  has_many :transactions, :class_name => "OrderTransaction"

  attr_accessor :card_number, :card_verification

  validate :validate_card, :on => :create

  def purchase
          response = GATEWAY.purchase(price_in_cents, credit_card, purchase_options)
          transactions.create!(:action => "purchase", :amount => price_in_cents, :response => response)
          #UserMailer.ordered("google.com", response.params.to_s, User.find(cart.user_id), cart).deliver
          cart.update_attribute(:purchased_at, Time.now) if response.success?
          response.success?
  end

  def price_in_cents
          (cart.total_price(User.find(cart.user_id))*100).round
  end

  private

  def purchase_options
          {
                  :ip => ip_address
          }
  end

  def validate_card
          unless credit_card.valid?
                  credit_card.errors.full_messages.each do |message|
                          errors.add :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

application controller

 def current_cart
    if session[:cart_id]
          @current_cart ||= Cart.find(session[:cart_id])
          session[:cart_id] = nil if @current_cart.purchased_at
    end
    if session[:cart_id].nil?
      @current_cart = Cart.create!
      session[:cart_id] = @current_cart.id
    end
    @current_cart
  end

Any insight is greatly appreciated.

هل كانت مفيدة؟

المحلول

Three ways to debug this:

1) Change from a redirect to rendering. This will keep the same @order object and likely show whats wrong in the view:

if @order.save
  #...          
else
  render :new
end

2) Tell rails to rails an exception if it can't save.

if @order.save!

This is useful when you're already render :new and can't find out what the errors are.

3) Add some logs:

if @order.save
  #...
else
  logger.debug @order.errors.full_messages.join(", ")
  render :new
end
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top