Ruby on Rails nil can't be coerced into BigDecimal

匿名 (未验证) 提交于 2019-12-03 01:38:01

问题:

Why do I get nil can't be coerced into BigDecimal when I try to perform a calculation: here's the code:

model/drink.rb

class Drink 

model/menu.rb

class Menu  :destroy     accepts_nested_attributes_for :drinks, :allow_destroy => true     #Validations  end 

*Drink is the (nested)child model and Menu the parent model When I attempt to create a new drink the browser display following error message nil can't be coerced into BigDecimal app/models/drink.rb:7:in 'total-amount' app/controllers/menus_controller.rb:47:in 'create' app/controllers/menus_controller.rb:46:in 'create'

app/db/migration

class CreateDrinks  8, :scale => 2       t.decimal :price, :precision => 8, :scale => 2       t.decimal :vat, :precision => 8, :scale => 2       t.references :menu        t.timestamps     end     add_index :drinks, :menu_id   end end 

controllers/drinks_controller.rb

   class DrinksController  @drinks }         end       end        # GET /drinks/1       # GET /drinks/1.json       def show         @drink = Drink.find(params[:id])          respond_to do |format|           format.html # show.html.erb           format.json { render :json => @drink }         end       end        # GET /drinks/new       # GET /drinks/new.json       def new         @drink = Drink.new          respond_to do |format|           format.html # new.html.erb           format.json { render :json => @drink }         end       end        # GET /drinks/1/edit       def edit         @drink = Drink.find(params[:id])       end        # POST /drinks       # POST /drinks.json       def create         @article = Drink.new(params[:drink])          respond_to do |format|           if @drink.save             format.html { redirect_to @drink, :notice => 'Drink was successfully created.' }             format.json { render :json => @drink, :status => :created, :location => @article }           else             format.html { render :action => "new" }             format.json { render :json => @drink.errors, :status => :unprocessable_entity }           end         end       end        # PUT /drinks/1       # PUT /drinks/1.json       def update         @drink = Drink.find(params[:id])          respond_to do |format|           if @drink.update_attributes(params[:drink])             format.html { redirect_to @drink, :notice => 'Drink was successfully updated.' }             format.json { head :ok }           else             format.html { render :action => "edit" }             format.json { render :json => @drink.errors, :status => :unprocessable_entity }           end         end       end        # DELETE /drinks/1       # DELETE /drinks/1.json       def destroy         @drink = Drink.find(params[:id])         @drink.destroy          respond_to do |format|           format.html { redirect_to drinks_url }           format.json { head :ok }         end       end      end  

Please can anyone tell me what's wrong with the code?

回答1:

If you want nil to be evaluated as 0.0 then you can do something like this:

def total_amount     self.total_amount = self.price.to_s.to_d * self.quantity.to_s.to_d end  

Or explicitly check for nil

def total_amount   if self.price && self.quantity     self.total_amount = self.price * self.quantity   else     self.total_amount = "0.0".to_d   end end  

The problem is really that your record fields aren't set like you expect them to be. Do you need to use validations to make sure that the price and quantity fields are set?

class Drink   validates :price, :presence => true      # Don't forget add DB validations, too :)   validates :quantity, :presence => true end 

That way you ensure that you don't get a nil value when calling #total_amount.



回答2:

You're not setting the quantity value anywhere so it is nil and nil cannot be coerced into a number for the multiplication.

Presumably your price is a decimal(n,2) (for some n) in the database so self.price is represented in Ruby as a BigDecimal object; that's why you're getting complaints about not being able to coerce to BigDecimal.

You can get a similar error out of irb like this:

>> 11 * nil TypeError: nil can't be coerced into Fixnum     from (irb):7:in `*' 

Your self.price is set though. If it wasn't then you'd get one of these:

NoMethodError: undefined method `*' for nil:NilClass 

You might want to add

validates_presence_of :quantity, :price 

(or possible stricter validations) to your model if you're requiring that they be set.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!