我有一个模型类page.rb:
class Page < ActiveRecord::Base
def paypal_url(return_url)
values = {
:business => 'seller_1229899173_biz@railscasts.com',
:cmd => '_cart',
:upload => 1,
:return => return_url,
:invoice => id
}
line_items.each_with_index do |item, index|
values.merge!({
"amount_#{index+1}" => item.unit_price,
"item_name_#{index+1}" => item.product.name,
"item_number_#{index+1}" => item.id,
"quantity_#{index+1}" => item.quantity
})
end
"https://www.sandbox.paypal.com/cgi-bin/webscr?" + values.to_query
end
end
在我的控制器中:
def order_form
if params[:commit] == "Proceed to Checkout"
redirect_to(@cart.paypal_url("/pages/order_online"))
end
但是当我点击&#34;继续结帐&#34;时,它会给我一个错误:
未定义的方法`paypal_url&#39;为零:NilClass
不知道我是否遗漏了什么或做错了什么?
谢谢!
答案 0 :(得分:1)
简单的答案是您的@cart
变量未填充任何数据
解决此问题的方法是在@cart
控制器中创建order_form
变量,如下所示:
def order_form
@cart = Cart.new cart_params #-> how to define your cart var?
redirect_to @cart.paypal_url "/pages/order_online"
end
我查看了您正在使用的Railscast,似乎他还在继续另一集,在那里他解释了如何使用标准ActiveRecord
创建购物车对象
更长的答案是,我认为您的系统存在缺陷,因为您在PayPal
模型中调用Page
方法(为什么?)
我们之前在Rails中设置了自己的购物车(您可以see here):
- 购物车
session model
# - &gt;将产品ID存储在购物车模型中- 的链接
Product
模型存储产品&amp;与购物车id
&#39;- 醇>
Order
控制器将数据发送到Paypal&amp;处理返回
以下是您的一些代码:
#config/routes.rb
get 'cart' => 'cart#index', :as => 'cart_index'
post 'cart/add/:id' => 'cart#add', :as => 'cart_add'
delete 'cart/remove(/:id(/:all))' => 'cart#delete', :as => 'cart_delete'
get 'checkout/paypal' => 'orders#paypal_express', :as => 'checkout'
get 'checkout/paypal/go' => 'orders#create_payment', :as => 'go_paypal'
get 'checkout/stripe' => 'orders#stripe', :as => 'stripe'
#app/models/cart_session.rb #-> "session based model"
class CartSession
#Initalize Cart Session
def initialize(session)
@session = session
@session[:cart] ||= {}
end
#Cart Count
def cart_count
if (@session[:cart][:products] && @session[:cart][:products] != {})
@session[:cart][:products].count
else
0
end
end
#Cart Contents
def cart_contents
products = @session[:cart][:products]
if (products && products != {})
#Determine Quantities
quantities = Hash[products.uniq.map {|i| [i, products.count(i)]}]
#Get products from DB
products_array = Product.find(products.uniq)
#Create Qty Array
products_new = {}
products_array.each{
|a| products_new[a] = {"qty" => quantities[a.id.to_s]}
}
#Output appended
return products_new
end
end
#Qty & Price Count
def subtotal
products = cart_contents
#Get subtotal of the cart items
subtotal = 0
unless products.blank?
products.each do |a|
subtotal += (a[0]["price"].to_f * a[1]["qty"].to_f)
end
end
return subtotal
end
#Build Hash For ActiveMerchant
def build_order
#Take cart objects & add them to items hash
products = cart_contents
@order = []
products.each do |product|
@order << {name: product[0].name, quantity: product[1]["qty"], amount: (product[0].price * 100).to_i }
end
return @order
end
#Build JSON Requests
def build_json
session = @session[:cart][:products]
json = {:subtotal => self.subtotal.to_f.round(2), :qty => self.cart_count, :items => Hash[session.uniq.map {|i| [i, session.count(i)]}]}
return json
end
end
#app/controllers/cart_controller.rb
# shows cart & allows you to click through to "buy"
class CartController < ApplicationController
include ApplicationHelper
#Index
def index
@items = cart_session.cart_contents
@shipping = Shipping.all
end
#Add
def add
session[:cart] ||={}
products = session[:cart][:products]
#If exists, add new, else create new variable
if (products && products != {})
session[:cart][:products] << params[:id]
else
session[:cart][:products] = Array(params[:id])
end
#Handle the request
respond_to do |format|
format.json { render json: cart_session.build_json }
format.html { redirect_to cart_index_path }
end
end
#Delete
def delete
session[:cart] ||={}
products = session[:cart][:products]
id = params[:id]
all = params[:all]
#Is ID present?
unless id.blank?
unless all.blank?
products.delete(params['id'])
else
products.delete_at(products.index(id) || products.length)
end
else
products.delete
end
#Handle the request
respond_to do |format|
format.json { render json: cart_session.build_json }
format.html { redirect_to cart_index_path }
end
end
end
#app/controllers/orders_controller.rb
#Paypal Express
def paypal_express
response = EXPRESS_GATEWAY.setup_purchase(total,
:items => cart_session.build_order,
:subtotal => subtotal,
:shipping => 50,
:handling => 0,
:tax => 0,
:return_url => url_for(:action => 'create_payment'),
:cancel_return_url => url_for(:controller => 'cart', :action => 'index')
)
redirect_to EXPRESS_GATEWAY.redirect_url_for(response.token)
end
#Create Paypal Payment
def create_payment
response = express_purchase
#transactions.create!(:action => "purchase", :amount => ((cart_session.subtotal * 100) + 50).to_i, :response => response)
#cart.update_attribute(:purchased_at, Time.now) if response.success?
response.success?
redirect_to cart_index_path
end
#Stripe
def stripe
credit_card = ActiveMerchant::Billing::CreditCard.new(
:number => "4242424242424242",
:month => "12",
:year => "2020",
:verification_value => "411"
)
purchaseOptions = {
:billing_address => {
:name => "Buyer Name",
:address1 => "Buyer Address Line 1",
:city => "Buyer City",
:state => "Buyer State",
:zip => "Buyer Zip Code"
}
}
response = STRIPE_GATEWAY.purchase(total, credit_card, purchaseOptions)
Rails.logger.debug response.inspect
@responder = response
render cart_index_path
end
private
def subtotal
(cart_session.subtotal * 100).to_i
end
def total
((cart_session.subtotal * 100) + 50).to_i
end
def express_purchase
EXPRESS_GATEWAY.purchase(total, express_purchase_options)
end
def express_purchase_options
{
:token => params[:token],
:payer_id => params[:PayerID]
}
end
def express_token=(token)
self[:express_token] = token
if new_record? && !token.blank?
details = EXPRESS_GATEWAY.details_for(token)
self.express_payer_id = details.payer_id
self.first_name = details.params["first_name"]
self.last_name = details.params["last_name"]
end
end
end