gpt4 book ai didi

ruby-on-rails - Rails 4 : Undefined method `total_price' for nil:NilClass, 订单 Controller

转载 作者:数据小太阳 更新时间:2023-10-29 07:31:48 25 4
gpt4 key购买 nike

我在处理订单时遇到问题。我已经在下面发布了错误。我认为这个问题与 OrderController.rb 中的 create 方法有关,我确实已经定义了 total_price 方法但是..除此之外我不确定如何解决这个问题。任何帮助,将不胜感激。谢谢。

enter image description here

class OrderTransaction
def initialize order, nonce
@order = order
@nonce = nonce
end

def execute
@result = Braintree::Transaction.sale(
amount: order.total_price,
payment_method_nonce: nonce
)
end

def ok?
@result.success?
end

private

attr_reader :order, :nonce
end

class Order < ActiveRecord::Base
belongs_to :user
has_many :order_items

def total_price
order_items.inject(0) { |sum, item| sum + item.total_price }
end
end

class OrdersController < ApplicationController
before_filter :initialize_cart

def index
@orders = Order.order(created_at: :desc).all
end

def create
@order_form = OrderForm.new(
user: User.new(order_params[:user]),
cart: @cart
)

if @order_form.save
notify_user
if charge_user
redirect_to root_path, notice: "Thank you for placing the order."
else
flash[:warning] = <<EOF
Your order ID is #{@order_form.order.id}.
<br/>
Something went wrong.
EOF
redirect_to new_payment_order_path(@order_form.order)
end
else
render "carts/checkout"
end
end

def update
@order = Order.find params[:id]
@previous_state = @order.state

if @order.update state_order_params
notify_user_about_state
redirect_to orders_path, notice: "Order was updated."
end
end


def new_payment
@order = Order.find params[:id]
@client_token = Braintree::ClientToken.generate
end

def pay
@order = Order.find params[:id]
transaction = OrderTransaction.new @order, params[:payment_method_nonce]
transaction.execute
if transaction.ok?
redirect_to root_path, notice: "Thank you for placing the order."
else
render "orders/new_payment"
end
end

private

def notify_user
@order_form.user.send_reset_password_instructions
OrderMailer.order_confirmation(@order_form.order).deliver
end

def notify_user_about_state
OrderMailer.state_changed(@order, @previous_state).deliver
end

def order_params
params.require(:order_form).permit(
user: [ :name, :phone, :address, :city, :country, :postal_code, :email ]
)
end

def charge_user
transaction = OrderTransaction.new @order, params[:payment_method_nonce]
transaction.execute
transaction.ok?
end

def state_order_params
params.require(:order).permit(:state)
end
end

class OrderItem < ActiveRecord::Base
belongs_to :order
belongs_to :product

def total_price
self.quantity * self.product.price
end
end

  class OrderForm
include ActiveModel::Model

attr_accessor :user, :order # credit_card
attr_writer :cart

def save
set_password_for_user

if valid?
persist
true
else
false
end
end

def has_errors?
user.errors.any?
end

private

def valid?
user.valid?
end

def persist
user.save
@order = Order.create! user: user

build_order_items
end

def set_password_for_user
user.password = Digest::SHA1.hexdigest(user.email + Time.now.to_s)[0..8]
end

def build_order_items
@cart.items.each do |item|
@order.order_items.create! product_id: item.product_id, quantity: item.quantity
end
end

end

class OrderItem < ActiveRecord::Base
belongs_to :order
belongs_to :product

def total_price
self.quantity * self.product.price
end
end

最佳答案

作为标准说明,任何 NilClass 错误基本上都意味着您尚未定义要操作的变量。

因此,解决问题的关键是找到 undefined variable 的原因,并填充它。


def execute
@result = Braintree::Transaction.sale(
amount: order.total_price,
payment_method_nonce: nonce
)
end

这就是 Rails 所说的变量未填充的地方。

但是,与编程中的许多问题一样,问题的原因可能没有定义...

我最初认为问题是您没有调用 @order。但是,该类使用 order 进行初始化,因此这应该不是问题。所以你必须看看你是如何调用这个类的:

transaction = OrderTransaction.new @order, params[:payment_method_nonce]

这推测 @order 已定义。

我猜不是。

这是我要做的:

def create
@order_form = OrderForm.new(
user: User.new(order_params[:user]),
cart: @cart
)

if @order_form.save
notify_user
@order = @order_form.order #-> not efficient but should create @order
if charge_user
redirect_to root_path, notice: "Thank you for placing the order."
else
flash[:warning] = <<EOF
Your order ID is #{@order_form.order.id}.
<br/>
Something went wrong.
EOF
redirect_to new_payment_order_path(@order_form.order)
end
else
render "carts/checkout"
end
end

就我个人而言,我认为这突出了您的代码结构的更深层次问题:

  • You're creating an OrderForm object and yet processing @order_form.order
  • Your controller is full of tiny methods which bloat it up big time
  • Your controller is for orders, yet builds OrderForm objects

我会尽我所能使我的 controller as thin as possible :

#app/controllers/orders_controller.rb
class OrdersController < ApplicationController
def new
@order = current_user.order.new
end
def create
@order = current_user.order.new order_params
if @order.save
@order.charge
end
end

private

def order_params
params.require(:order).permit(:x, :y, :z, order_products_attributes: [:product, :qty])
end
end

我会有一个更加模块化的模型结构:

#app/models/order.rb
class Order < ActiveRecord::Base
belongs_to :user
has_many :order_products
has_many :products, through: :order_products, extend ProductQty
has_many :payments, inverse_of: :order

scope :cart, -> { order_products }

def total_price
products.pluck(:price, :qty) #-> need to work out
end

def charge
payment = payments.create
payment.execute ? payment.success : payment.error #-> something conditional
end
end

#app/models/order_product.rb
class OrderProduct < ActiveRecord::Base
#columns id | order_id | product_id | qty | created_at | updated_at
belongs_to :order
belongs_to :product

end

#app/models/payment.rb
class Payment < ActiveRecord::Base
belongs_to :order, inverse_of: :payments

def execute
Braintree::Transaction.sale(amount: order.total_price)
end
end

#app/models/product.rb
class Product < ActiveRecord::Base
has_many :order_products
has_many :orders, through: :order_products
end

#app/models/concerns/product_qty.rb
module ProductQty

#Load
def load
products.each do |qty|
proxy_association.target << qty
end
end

#Private
private

#Products
def products
return_array = []
through_collection.each_with_index do |through,i|
associate = through.send(reflection_name)
associate.assign_attributes({qty: items[i]})
return_array.concat Array.new(1).fill( associate )
end
return_array
end

#######################
# Variables #
#######################

#Association
def reflection_name
proxy_association.source_reflection.name
end

#Foreign Key
def through_source_key
proxy_association.reflection.source_reflection.foreign_key
end

#Primary Key
def through_primary_key
proxy_association.reflection.through_reflection.active_record_primary_key
end

#Through Name
def through_name
proxy_association.reflection.through_reflection.name
end

#Through
def through_collection
proxy_association.owner.send through_name
end

#Captions
def items
through_collection.map(&:qty)
end

#Target
def target_collection
proxy_association.target
end

end

我想在某个地方包含购物车,我得改天再做。

现在,您可以执行以下操作:

@order = current_user.orders.find params[:id]
@order.products.each do |product|
product.qty #-> 5

@order.total_price #-> prices * qtys

--

这不是完整的或未测试的,但我希望它向您展示如何通过模块化显着改进您的代码结构。 IE 将尽可能多的方法与您的对象相关联。

简而言之,您应该能够执行以下操作:

@order = current_users.orders.find params[:id]
if @order.payments.any?
@payment = @order.payment.first
@payment.success?
end

关于ruby-on-rails - Rails 4 : Undefined method `total_price' for nil:NilClass, 订单 Controller ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32792639/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com