nil can't be coerced into BigDecimal

hi guys im playing with RoR with the environment of rails 3 ruby 1.9 i
got stuck in

nil can't be coerced into BigDecimal

error

i need to get the total cost of the products inside the cart i know
where the problem is(i think) but i almost did every thing
cart/show.html.rb

<div class="cart_title" >Your Cart</div>
    <table>
        <% for item in @cart.line_items %>
    <tr>
        <td><%= item.quantity %>&times;</td>
        <td><%= item.product.title %></td>
    <td class="item_price" ><%= number_to_currency(item.total_price)
%></td>
    </tr>
    <% end %>
        <tr class="total_line" >
        <td colspan="2" >Total</td>
        <td class="total_cell" ><%=
number_to_currency(@cart.total_price) %></td>
    </tr>
    </table>
        <%= button_to 'Empty cart', @cart, :method => :delete,
        :confirm => 'Are you sure?' %>

model/line_item.rb

  def total_price
    line_items.to_a.sum { |item| item.total_price }
  end
model/cart.rb

def total_price
    product.price * quantity
  end
my second option is

def total_price
     if product.price
       product.price * quantity
     else
       product.price = "0.0".to_d
     end
   end
but still this wont work

thanks more power to us!

hi guys im playing with RoR with the environment of rails 3 ruby 1.9 i

got stuck in

nil can’t be coerced into BigDecimal

error

i need to get the total cost of the products inside the cart i know

where the problem is(i think) but i almost did every thing

cart/show.html.rb

Your Cart
<table>

    <% for item in @cart.line_items %>

<tr>

    <td><%= item.quantity %>&times;</td>

    <td><%= item.product.title %></td>

<td class="item_price" ><%= number_to_currency(item.total_price)

%>

</tr>

<% end %>

    <tr class="total_line" >

    <td colspan="2" >Total</td>

    <td class="total_cell" ><%=

number_to_currency(@cart.total_price) %>

</tr>

</table>

    <%= button_to 'Empty cart', @cart, :method => :delete,

    :confirm => 'Are you sure?' %>

model/line_item.rb

def total_price

line_items.to_a.sum { |item| item.total_price }

end

model/cart.rb

def total_price

product.price  * quantity

end

my second option is

def total_price

 if product.price

   product.price * quantity

 else

   product.price = "0.0".to_d

This code is assigning a 0 to fixed price of a product
(most probably not what is intended). Probably simply
return a 0 (in BigDecimal) here.

end

end

but still this wont work

Is there a business rule that each item must realistically have
a quantity and product (and that product must have a price) ?

In that case I suggest:

  • add validations for the presence of these values

    (presence of quantity and product on item
    presence of price on product)

  • write code like:

def total_price

 if self.valid?
  product.price * quantity

 else

   0.to_d

 end

end

Another possible gotcha is that “item.product_id” is available
(e.g. from a select box), but item.product is not yet associated
(you may need to override the product_id= setter for that e.g.

def product_id=(product_id)
self.product = Product.find_by_id(product_id)
super
end

HTH,

Peter

Is there a business rule that each item must realistically have
a quantity and product (and that product must have a price) ?

uhm im following agile web development rails actualy the snippets are
from the book

* add validations for the presence of these values
(presence of quantity and product on item
presence of price on product)

i already validated the price
of each item in CRUD

model/product.rb
  validates :price, :numericality => {:greater_than_or_equal_to =>
0.01}

im trying to to follow your suggestion but nothing happens it was
still the same as it was :frowning:

For clarity. It is not because a validation is present that the
value is always present in memory (in the database, using the
standard techniques for saving, only valid data should ever be

really saved).

Is the data for the item valid?

  • quantity
  • product
  • product_id

Check out the values of those 3.

HTH,

Peter

yes those data are valid actualy a while ago it worked but when i
clear and destroy the cart it returned to this error
very much appreciated for your effort thank you

app/models/line_item.rb:24:in `*'
app/models/line_item.rb:24:in `total_price'
app/views/carts/show.html.erb:7:in `block in
_app_views_carts_show_html_erb___389431939__618846538'
activerecord (3.1.1)
lib/active_record/associations/collection_proxy.rb:91:in `each'
activerecord (3.1.1)
lib/active_record/associations/collection_proxy.rb:91:in
`method_missing'
app/views/carts/show.html.erb:3:in
`_app_views_carts_show_html_erb___389431939__618846538'
actionpack (3.1.1) lib/action_view/template.rb:144:in `block in render'
activesupport (3.1.1) lib/active_support/notifications.rb:55:in
`instrument'
actionpack (3.1.1) lib/action_view/template.rb:142:in `render'
actionpack (3.1.1) lib/action_view/renderer/template_renderer.rb:40:in
`block (2 levels) in render_template'
actionpack (3.1.1) lib/action_view/renderer/abstract_renderer.rb:33:in
`block in instrument'
activesupport (3.1.1) lib/active_support/notifications.rb:53:in `block
in instrument'
activesupport (3.1.1)
lib/active_support/notifications/instrumenter.rb:21:in `instrument'
activesupport (3.1.1) lib/active_support/notifications.rb:53:in
`instrument'
actionpack (3.1.1) lib/action_view/renderer/abstract_renderer.rb:33:in
`instrument'
actionpack (3.1.1) lib/action_view/renderer/template_renderer.rb:39:in
`block in render_template'
actionpack (3.1.1) lib/action_view/renderer/template_renderer.rb:47:in
`render_with_layout'
actionpack (3.1.1) lib/action_view/renderer/template_renderer.rb:38:in
`render_template'
actionpack (3.1.1) lib/action_view/renderer/template_renderer.rb:12:in
`block in render'
actionpack (3.1.1) lib/action_view/renderer/abstract_renderer.rb:22:in
`wrap_formats'
actionpack (3.1.1) lib/action_view/renderer/template_renderer.rb:9:in
`render'
actionpack (3.1.1) lib/action_view/renderer/renderer.rb:36:in
`render_template'
actionpack (3.1.1) lib/action_view/renderer/renderer.rb:17:in `render'
actionpack (3.1.1) lib/abstract_controller/rendering.rb:120:in
`_render_template'
actionpack (3.1.1) lib/action_controller/metal/streaming.rb:250:in
`_render_template'
actionpack (3.1.1) lib/abstract_controller/rendering.rb:114:in
`render_to_body'
actionpack (3.1.1) lib/action_controller/metal/renderers.rb:30:in
`render_to_body'
actionpack (3.1.1) lib/action_controller/metal/compatibility.rb:43:in
`render_to_body'
actionpack (3.1.1) lib/abstract_controller/rendering.rb:99:in `render'
actionpack (3.1.1) lib/action_controller/metal/rendering.rb:16:in
`render'
actionpack (3.1.1) lib/action_controller/metal/instrumentation.rb:40:in
`block (2 levels) in render'
activesupport (3.1.1) lib/active_support/core_ext/benchmark.rb:5:in
`block in ms'
/home/led/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/benchmark.rb:310:in
`realtime'
activesupport (3.1.1) lib/active_support/core_ext/benchmark.rb:5:in `ms'
actionpack (3.1.1) lib/action_controller/metal/instrumentation.rb:40:in
`block in render'
actionpack (3.1.1) lib/action_controller/metal/instrumentation.rb:78:in
`cleanup_view_runtime'
activerecord (3.1.1)
lib/active_record/railties/controller_runtime.rb:24:in
`cleanup_view_runtime'
actionpack (3.1.1) lib/action_controller/metal/instrumentation.rb:39:in
`render'
actionpack (3.1.1) lib/action_controller/metal/implicit_render.rb:10:in
`default_render'
actionpack (3.1.1) lib/action_controller/metal/mime_responds.rb:268:in
`block in retrieve_response_from_mimes'
actionpack (3.1.1) lib/action_controller/metal/mime_responds.rb:195:in
`call'
actionpack (3.1.1) lib/action_controller/metal/mime_responds.rb:195:in
`respond_to'
app/controllers/carts_controller.rb:22:in `show'
actionpack (3.1.1) lib/action_controller/metal/implicit_render.rb:4:in
`send_action'
actionpack (3.1.1) lib/abstract_controller/base.rb:167:in
`process_action'
actionpack (3.1.1) lib/action_controller/metal/rendering.rb:10:in
`process_action'
actionpack (3.1.1) lib/abstract_controller/callbacks.rb:18:in `block in
process_action'
activesupport (3.1.1) lib/active_support/callbacks.rb:416:in
`_run__371692982__process_action__266900328__callbacks'
activesupport (3.1.1) lib/active_support/callbacks.rb:386:in
`_run_process_action_callbacks'
activesupport (3.1.1) lib/active_support/callbacks.rb:81:in
`run_callbacks'
actionpack (3.1.1) lib/abstract_controller/callbacks.rb:17:in
`process_action'
actionpack (3.1.1) lib/action_controller/metal/rescue.rb:17:in
`process_action'
actionpack (3.1.1) lib/action_controller/metal/instrumentation.rb:30:in
`block in process_action'
activesupport (3.1.1) lib/active_support/notifications.rb:53:in `block
in instrument'
activesupport (3.1.1)
lib/active_support/notifications/instrumenter.rb:21:in `instrument'
activesupport (3.1.1) lib/active_support/notifications.rb:53:in
`instrument'
actionpack (3.1.1) lib/action_controller/metal/instrumentation.rb:29:in
`process_action'
actionpack (3.1.1) lib/action_controller/metal/params_wrapper.rb:201:in
`process_action'
activerecord (3.1.1)
lib/active_record/railties/controller_runtime.rb:18:in `process_action'
actionpack (3.1.1) lib/abstract_controller/base.rb:121:in `process'
actionpack (3.1.1) lib/abstract_controller/rendering.rb:45:in `process'
actionpack (3.1.1) lib/action_controller/metal.rb:193:in `dispatch'
actionpack (3.1.1) lib/action_controller/metal/rack_delegation.rb:14:in
`dispatch'
actionpack (3.1.1) lib/action_controller/metal.rb:236:in `block in
action'
actionpack (3.1.1) lib/action_dispatch/routing/route_set.rb:65:in `call'
actionpack (3.1.1) lib/action_dispatch/routing/route_set.rb:65:in
`dispatch'
actionpack (3.1.1) lib/action_dispatch/routing/route_set.rb:29:in `call'
rack-mount (0.8.3) lib/rack/mount/route_set.rb:152:in `block in call'
rack-mount (0.8.3) lib/rack/mount/code_generation.rb:96:in `block in
recognize'
rack-mount (0.8.3) lib/rack/mount/code_generation.rb:96:in
`optimized_each'
rack-mount (0.8.3) lib/rack/mount/code_generation.rb:95:in `recognize'
rack-mount (0.8.3) lib/rack/mount/route_set.rb:141:in `call'
actionpack (3.1.1) lib/action_dispatch/routing/route_set.rb:532:in
`call'
actionpack (3.1.1)
lib/action_dispatch/middleware/best_standards_support.rb:17:in `call'
rack (1.3.6) lib/rack/etag.rb:23:in `call'
rack (1.3.6) lib/rack/conditionalget.rb:25:in `call'
actionpack (3.1.1) lib/action_dispatch/middleware/head.rb:14:in `call'
actionpack (3.1.1) lib/action_dispatch/middleware/params_parser.rb:21:in
`call'
actionpack (3.1.1) lib/action_dispatch/middleware/flash.rb:243:in `call'
rack (1.3.6) lib/rack/session/abstract/id.rb:195:in `context'
rack (1.3.6) lib/rack/session/abstract/id.rb:190:in `call'
actionpack (3.1.1) lib/action_dispatch/middleware/cookies.rb:331:in
`call'
activerecord (3.1.1) lib/active_record/query_cache.rb:62:in `call'
activerecord (3.1.1)
lib/active_record/connection_adapters/abstract/connection_pool.rb:477:in
`call'
actionpack (3.1.1) lib/action_dispatch/middleware/callbacks.rb:29:in
`block in call'
activesupport (3.1.1) lib/active_support/callbacks.rb:392:in
`_run_call_callbacks'
activesupport (3.1.1) lib/active_support/callbacks.rb:81:in
`run_callbacks'
actionpack (3.1.1) lib/action_dispatch/middleware/callbacks.rb:28:in
`call'
actionpack (3.1.1) lib/action_dispatch/middleware/reloader.rb:68:in
`call'
rack (1.3.6) lib/rack/sendfile.rb:101:in `call'
actionpack (3.1.1) lib/action_dispatch/middleware/remote_ip.rb:48:in
`call'
actionpack (3.1.1)
lib/action_dispatch/middleware/show_exceptions.rb:47:in `call'
railties (3.1.1) lib/rails/rack/logger.rb:13:in `call'
rack (1.3.6) lib/rack/methodoverride.rb:24:in `call'
rack (1.3.6) lib/rack/runtime.rb:17:in `call'
activesupport (3.1.1)
lib/active_support/cache/strategy/local_cache.rb:72:in `call'
rack (1.3.6) lib/rack/lock.rb:15:in `call'
actionpack (3.1.1) lib/action_dispatch/middleware/static.rb:53:in `call'
railties (3.1.1) lib/rails/engine.rb:456:in `call'
railties (3.1.1) lib/rails/rack/content_length.rb:16:in `call'
railties (3.1.1) lib/rails/rack/log_tailer.rb:14:in `call'
rack (1.3.6) lib/rack/handler/webrick.rb:59:in `service'
/home/led/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/webrick/httpserver.rb:111:in
`service'
/home/led/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/webrick/httpserver.rb:70:in
`run'
/home/led/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/webrick/server.rb:183:in
`block in start_thread'

its the full trace of the error cant seems to find it im a week old in
ruby on rails development

hi guys im playing with RoR with the environment of rails 3 ruby 1.9 i
got stuck in

nil can't be coerced into BigDecimal

  def total_price
   line_items.to_a.sum { |item| item.total_price }
end
model/cart.rb

That error would be expected when some of line_items.total_price returns nil. Moreover you can sum total prices without .to_a, that would be more efficient.

def total_price
   product.price * quantity
end

def total_price
    if product.price
      product.price * quantity
    else
      product.price = "0.0".to_d

  It is not necessary to write attribute :price, just let it return zero. 0.to_d in this case.
  

    end
  end

Now. before test it again, check in the database if any product has a nil or any non-bigdecimal value.

nil can't be coerced into BigDecimal

  def total_price
   line_items.to_a.sum { |item| item.total_price }
end
model/cart.rb

That error would be expected when some of line_items.total_price returns
nil. Moreover you can sum total prices without .to_a, that would be more
efficient.

tried to applying this but gotting the problem in the view

def total_price
   product.price * quantity
end

def total_price
    if product.price
      product.price * quantity
    else
      product.price = "0.0".to_d

  It is not necessary to write attribute :price, just let it return
zero. 0.to_d in this case.

i tried this and it worked out but when reseting the cart it return the
error

    end
  end

Now. before test it again, check in the database if any product has a
nil or any non-bigdecimal value.

this is being weird when i tried your suggestion it worked out but when
i
clear delete the cart again it return to the error :frowning:

i tried refactoring my destroy method now its working fine but my second
issue is when i add item to the cart at first attemp it returns to that
error again but returning to the product list it worked fine im just
wondering if my add_product is code is ok?

def add_product(product_id)
    current_item = line_items.where(:product_id => product_id).first

     if current_item
        current_item.quantity = current_item.quantity.to_i + 1
      else
        current_item = LineItem.new(:product_id=>product_id)
        line_items << current_item
      end
        current_item
   end

I didn't see you code completely, but

line_items.to_a.sum { |item| item.total_price }

How can it count correct if only ONE item in the cart? :slight_smile:

Obviously, if you want to get Array, use Array.wrap method like this:

Array.wrap(line_items).sum { |item| item.total_price }

Valery Kvon wrote in post #1047975:

I didn't see you code completely, but

line_items.to_a.sum { |item| item.total_price }

How can it count correct if only ONE item in the cart? :slight_smile:

Obviously, if you want to get Array, use Array.wrap method like this:

Array.wrap(line_items).sum { |item| item.total_price }

i tried Array.wrap(line_items).sum { |item| item.total_price }
also it worked same as the
line_items.to_a.sum { |item| item.total_price }
(i think?)
but im having the issue of not counting my first attemp maybe my
add_product code is wrong?

def add_product(product_id)
    current_item = line_items.where(:product_id => product_id).first

     if current_item
        current_item.quantity = current_item.quantity.to_i + 1
      else
        current_item = LineItem.new(:product_id=>product_id)
        line_items << current_item
      end
        current_item
   end

it feels like im adding a nil value at my first attemp of adding a
product into my cart?
btw thanks for your concern with my post :slight_smile:

It is not the item that is nil but total_price. If it were the item
that were nil then you would get an error saying that nil did not have
a method total_price. Where are you setting total_price when you do
LineItem.new.

Colin

def add_product(product_id)
   current_item = line_items.where(:product_id => product_id).first

    if current_item
       current_item.quantity = current_item.quantity.to_i + 1
     else
       current_item = LineItem.new(:product_id=>product_id)
       line_items << current_item

  Ok, let's imagine. You add new LineItem and product.price is nil or quantity is nil
  then
  product.price * quantity
  would raise error "nil can't be coerced into…"

  Check if product price or quantity is nil after initialize LineItem.new

Colin Law wrote in post #1047978:

it feels like im adding a nil value at my first attemp of adding a
product into my cart?

It is not the item that is nil but total_price. If it were the item
that were nil then you would get an error saying that nil did not have
a method total_price. Where are you setting total_price when you do
LineItem.new.

i belive im setting it in the current_item it self
current_item = LineItem.new(:product_id=>product_id)

Show us the code of LineItem class.

This method raises the error on a new instance. To avoid it, it must return BigDec anytime. In your case product.price is nil or quantity is nil..

def total_price
   product.price * quantity
end

As I wrote above. This sets the product_id, but not
necessarily the “product” association. Check values of

  • current_item.product_id
  • current_item.product
    right after this line.

HTH,

Peter

Valery Kvon wrote in post #1047982:

Show us the code of LineItem class.

This method raises the error on a new instance. To avoid it, it must
return BigDec anytime. In your case product.price is nil or quantity is
nil..

def total_price
   product.price * quantity
end

class LineItem < ActiveRecord::Base
  belongs_to :product
  belongs_to :cart

  def total_price
     if product.price
       product.price = product.price * quantity
     else
        0.to_d
     end
   end
end

this is my model/line item.rb

So.

I agree that:
1) current_item = LineItem.new(:product_id=>product_id) = BAD IDEA. Because, if you pass the invalid product ID, LineItem would be initialized as well, but the .product association would return nil.

2) Actually I didn't see how quantity is set up? Looking at your previous code it must be method 'quantity'.

PS. Why are you writing product.price=?

Valery Kvon wrote in post #1047990:

  end
end

So.

I agree that:
1) current_item = LineItem.new(:product_id=>product_id) = BAD IDEA.
Because, if you pass the invalid product ID, LineItem would be
initialized as well, but the .product association would return nil.

do you think current_item = line_items.build(:product_id => product_id)
is better?

2) Actually I didn't see how quantity is set up? Looking at your
previous code it must be method 'quantity'.

i dont have a method quantity

PS. Why are you writing product.price=?

i belive it is same with product.price * quantity
to show the sum of all products inside my cart

Valery Kvon wrote in post #1047990:

I agree that:
1) current_item = LineItem.new(:product_id=>product_id) = BAD IDEA.
Because, if you pass the invalid product ID, LineItem would be
initialized as well, but the .product association would return nil.

do you think current_item = line_items.build(:product_id => product_id)
is better?

no, the correct way is:

product = Product.find(product_id) # it will raise AcriveRecord::RecordNotFound if invalid product_id passed.
current_item = LineItem.new(:product => product) # or current_item = LineItem.new; current_item.product = product

2) Actually I didn't see how quantity is set up? Looking at your
previous code it must be method 'quantity'.

i dont have a method quantity

In this case it does not work ever. def total_count - is an instance method.
If you use 'quantity', so it just MUST be an another instance method or local variable. There is something wrong with app's logic.

PS. Why are you writing product.price=?

i belive it is same with product.price * quantity
to show the sum of all products inside my cart

Logic, logic, logic….

product - is a stand alone instance or One product. Why Would it ever have the multiplied price with 'quantity' ?.

I remember many years ago I read the beginner's book "Agile Web Development with Rails", is that example from it? I think you missed something.