Rails模型中的项目总和 - Nil类错误

问题描述 投票:0回答:1

我正在尝试将产品模型和服务模型中的值一起添加到Order模型中。我会发布下面的模型,以便关系清晰。我尝试了各种选项,但基本上如果我添加了一个产品项目,并且没有服务项目,它会崩溃,反之亦然。这是消息:NoMethodError (undefined method `price' for nil:NilClass):

我从to_i添加了here试图将Nil变为0但仍然没有运气。我哪里错了?

class Order < ApplicationRecord
  has_many :line_items
  before_save :update_total
  before_update :update_total
  belongs_to :user, optional: true

  def total_service_items
    self.line_items.collect { |item| item.service.price.to_i * item.quantity }.sum
  end

  def total_product_items
    self.line_items.collect { |item| item.product.price.to_i * item.quantity }.sum
  end

  def calculate_total
    total_service_items + total_product_items
  end

  def update_total
    self.total_price = calculate_total
  end    
end

行项目模型

class LineItem < ApplicationRecord
  belongs_to :order, optional: true
  belongs_to :product, optional: true
  belongs_to :service, optional: true
end

服务模式

class Service < ApplicationRecord
    has_many :line_items
end

产品型号

class Product < ApplicationRecord
    has_many :line_items
end

控制器(此控制器的Create方法正在执行此操作)

class LineItemsController < ApplicationController     

  def create
    @order = current_order
    @item = @order.line_items.new(item_params)
    @order.save
  end

      def item_params
        params.require(:line_item).permit(:quantity, :service_id, :product_id, :unit_price, :order_id)
    end
end
ruby-on-rails
1个回答
1
投票

你的一个或多个协会可能是nil - optional: true密钥表明这可能正在发生。

您可以检查这些关联是否在您的区块中是present?,或者您可以将total分配给line_items,这将为您完成此工作。我建议后者:

class LineItem < ApplicationRecord
  def total_as_product
    return 0 unless product.present? 
    product.price.to_i * self.quantity
  end 

  def total_as_service
    return 0 unless service.present?
    service.price.to_i * self.quantity
  end 
end 

在您的订单模型中:

def total_product_items
  self.line_items.collect { |item| item.total_as_product }.sum
end 

def total_service_items
  self.line_items.collect { |item| item.total_as_service }.sum
end 

随着时间的推移要记住:在这里可以进行一些进一步的优化 - 例如eager-loading your associations,这样你就不会遇到一些n + 1个查询。

另外:当before_update存在时,before_save是多余的。您可以安全地删除before_update并获得相同的行为。

© www.soinside.com 2019 - 2024. All rights reserved.