我正在尝试将产品模型和服务模型中的值一起添加到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
你的一个或多个协会可能是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
并获得相同的行为。