nil不能被强制转换为BigDecimal - Ruby On Rails

时间:2016-08-16 23:27:33

标签: ruby-on-rails ruby

我已经看到了与此类似的其他问题,但没有一个完全相同(我还是有点初学者)。如果有另一个相同的线程,请告诉我!谢谢!

更新 我忘了添加此代码。哪个是用于添加数量的迁移文件。

class AddQuantityToProductItems < ActiveRecord::Migration[5.0]
  def change
    add_column :product_items, :quantity, :integer, default: 1
  end
end

我从下面的代码中继续收到错误“nil无法强制转换为BigDecimal”( ProductItem Model:

class ProductItem < ApplicationRecord
  belongs_to :product
  belongs_to :cart

  def total_price
    product.price * quantity
  end  
end

以下是购物车型号:

class Cart < ApplicationRecord
  has_many :product_items, dependent: :destroy

  def add_product(product_id)
    current_item = product_items.find_by(product_id: product_id)
    if current_item
      current_item.quantity += 1
    else
      current_item = product_items.build(product_id: product_id)
    end
    current_item
  end

  def total_price
    product_items.to_a.sum{|item| item.total_price}
  end
end

产品型号:

class Product < ApplicationRecord
  before_destroy :ensure_not_product_item
  has_many :product_items
  validates :title, :description, presence: true
  validates :price, numericality: {greater_than_or_equal_to: 0.01}
  validates :title, uniqueness: true
  has_attached_file :image, styles: { medium: "300x300>", thumb:       "100x100>" }
  validates_attachment_content_type :image, content_type: /\Aimage\/.*\Z/

  def ensure_not_product_item
    if product_items.empty?
      return true
    else
      errors.add(:base, 'Product Items')
      return false
    end
  end
end

ProductItems Controller:

class ProductItemsController < ApplicationController

  include CurrentCart
  before_action :set_cart, only: [:create]
  before_action :set_product_item, only: [:show, :destroy]

  def create
    product = Product.find(params[:product_id])
    @product_item = @cart.add_product(product.id)
    if @product_item.save
      redirect_to shop_url, notice: 'Your Product was added to the cart!'
    else
      render :new
    end
  end

  private

  def set_product_item
    @product_item = ProductItem.find(params[:id])
  end

  def product_item_params
    params.require(:product_item).permit(:product_id)
  end

end

schema.rb

中的产品项目和产品代码
create_table "product_items", force: :cascade do |t|
  t.integer  "product_id"
  t.integer  "cart_id"
  t.datetime "created_at", null: false
  t.datetime "updated_at", null: false
  t.integer  "quantity"
  t.index ["cart_id"], name: "index_product_items_on_cart_id"
  t.index ["product_id"], name: "index_product_items_on_product_id"
end

create_table "products", force: :cascade do |t|
  t.string   "title"
  t.string   "image"
  t.text     "description"
  t.decimal  "price"
  t.datetime "created_at",         null: false
  t.datetime "updated_at",         null: false
  t.string   "image_file_name"
  t.string   "image_content_type"
  t.integer  "image_file_size"
  t.datetime "image_updated_at"
end

如果需要任何其他文件,我很乐意发布它们。我确定这很简单,我似乎无法弄明白。也许我很难找到问题。大声笑。 感谢您抽出宝贵时间提供帮助!

2 个答案:

答案 0 :(得分:1)

根据它的声音,您在创建新产品项时没有初始化quantity属性。

您可以通过在quantity

中添加after_initialize块来初始化ProductItem属性
class ProductItem < ApplicationRecord
  after_initialize do
    self.quantity ||= 1
  end
end

或者,您可以在创建产品项时在quantity方法中设置Cart#add_product属性:

class Cart < ApplicationRecord
  def add_product(product_id)
    current_item = product_items.find_by(product_id: product_id)
    if current_item
      current_item.quantity += 1
    else
      # initialize the quantity value when creating a new item
      current_item = product_items.build(product_id: product_id, quantity: 1)
    end
    current_item
  end
end

另一种方法是在ProductItem#total_price方法中设置默认值:

class ProductItem < ApplicationRecord
  def total_price
    product.price * (quantity || 1)
  end  
end

就个人而言,我会使用after_initialize方法,因为它是最一致的选项,因为quantity 始终有值。

答案 1 :(得分:0)

您的代码正在尝试使用nil值进行算术运算,因此消息nil can't be coerced into BigDecimal

至于为什么会发生这种情况,您需要进行一些挖掘,以找出错误出现在代码中的哪个位置。一个线索是错误意味着nil值位于操作的右侧,例如:

bd = BigDecimal.new("0")
bd + nil # => nil can't be coerced into BigDecimal

而不是:

nil + bd # => undefined method '+' for nil:NilClass