I am NEW ON learning Ruby on Rails. I am following the book Agile Web Development with Rails 4. I nearly have finished Chapter 10: Smarter Card. I have to create a Method for LineItem and Cart models that returns the total price for the individual item and entire card. When I start my server, I get the error notification "nil can't be coerced into BigDecimal".
What was weird: It worked.
Started GET "/carts/38" for 127.0.0.1 at 2014-10-24 22:16:41 +0200
Processing by CartsController#show as HTML
Parameters: {"id"=>"38"}
Cart Load (0.1ms) SELECT "carts".* FROM "carts" WHERE "carts"."id" = ? LIMIT 1 [["id", 38]]
LineItem Load (0.1ms) SELECT "line_items".* FROM "line_items" WHERE "line_items"."cart_id" = ? [["cart_id", 38]]
Product Load (0.1ms) SELECT "products".* FROM "products" WHERE "products"."id" = ? LIMIT 1 [["id", 4]]
Rendered carts/show.html.erb within layouts/application (4.3ms)
Completed 200 OK in 51ms (Views: 49.2ms | ActiveRecord: 0.3ms)
Started GET "/assets/turbolinks.js?body=1" for 127.0.0.1 at 2014-10-24 22:16:41 +0200
Started GET "/assets/application.css?body=1" for 127.0.0.1 at 2014-10-24 22:16:41 +0200
Started GET "/assets/carts.js?body=1" for 127.0.0.1 at 2014-10-24 22:16:41 +0200
Started GET "/assets/jquery.js?body=1" for 127.0.0.1 at 2014-10-24 22:16:41 +0200
Started GET "/assets/jquery_ujs.js?body=1" for 127.0.0.1 at 2014-10-24 22:16:41 +0200
Started GET "/assets/line_items.js?body=1" for 127.0.0.1 at 2014-10-24 22:16:41 +0200
Started GET "/assets/store.js?body=1" for 127.0.0.1 at 2014-10-24 22:16:41 +0200
Started GET "/assets/products.js?body=1" for 127.0.0.1 at 2014-10-24 22:16:41 +0200
Started GET "/assets/application.js?body=1" for 127.0.0.1 at 2014-10-24 22:16:41 +0200
Started GET "/assets/logo.png" for 127.0.0.1 at 2014-10-24 22:16:41 +0200
Started DELETE "/carts/38" for 127.0.0.1 at 2014-10-24 22:19:11 +0200
Processing by CartsController#destroy as HTML
Parameters: {"authenticity_token"=>"EhOlirn9iTrL0fXoxCLWWKQSsSPN4lNWoF0Rv2M873M=", "id"=>"38"}
Cart Load (0.1ms) SELECT "carts".* FROM "carts" WHERE "carts"."id" = ? LIMIT 1 [["id", 38]]
(0.1ms) begin transaction
LineItem Load (0.1ms) SELECT "line_items".* FROM "line_items" WHERE "line_items"."cart_id" = ? [["cart_id", 38]]
SQL (0.3ms) DELETE FROM "line_items" WHERE "line_items"."id" = ? [["id", 35]]
SQL (0.1ms) DELETE FROM "carts" WHERE "carts"."id" = ? [["id", 38]]
(0.6ms) commit transaction
Redirected to http://0.0.0.0:3000/
Completed 302 Found in 4ms (ActiveRecord: 1.2ms)
After I pressed the button "Empty Cart" and pressed the refresh button I got the error.
Started GET "/carts/36" for 127.0.0.1 at 2014-10-24 23:18:29 +0200
ActiveRecord::SchemaMigration Load (0.4ms) SELECT "schema_migrations".* FROM "schema_migrations"
Processing by CartsController#show as HTML
Parameters: {"id"=>"36"}
Cart Load (0.2ms) SELECT "carts".* FROM "carts" WHERE "carts"."id" = ? LIMIT 1 [["id", 39]]
LineItem Load (0.7ms) SELECT "line_items".* FROM "line_items" WHERE "line_items"."cart_id" = ? [["cart_id", 39]]
Product Load (0.2ms) SELECT "products".* FROM "products" WHERE "products"."id" = ? LIMIT 1 [["id", 4]]
Rendered carts/show.html.erb within layouts/application (67.2ms)
Completed 500 Internal Server Error in 96ms
ActionView::Template::Error (nil can't be coerced into BigDecimal):
9: <tr>
10: <td><%= item.quantity %>×</td>
11: <td><%= item.product.title %></td>
12: <td class="item_price"><%= number_to_currency(item.total_price) %></td>
13: </tr>
14: <% end %>
15:
app/models/line_item.rb:9:in `*'
app/models/line_item.rb:9:in `total_price'
app/views/carts/show.html.erb:12:in `block in _ app_views_carts_show_html_erb___3008945911568791515_70186161526860'
app/views/carts/show.html.erb:8:in ` _app_views_carts_show_html_erb___3008945911568791515_70186161526860'
Rendered /Users/eichmann/.rvm/gems/ruby-2.1.2/gems/actionpack- 4.1.4/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb (1.4ms)
Rendered /Users/eichmann/.rvm/gems/ruby-2.1.2/gems/actionpack-4.1.4/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb (0.9ms)
Rendered /Users/eichmann/.rvm/gems/ruby-2.1.2/gems/actionpack-4.1.4/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb within rescues/layout (12.8ms)
Model of the Cart
class Cart < ActiveRecord::Base
has_many :line_items, dependent: :destroy
def add_product(product_id)
current_item = line_items.find_by(product_id: product_id)
if current_item
current_item.quantity = current_item.quantity.to_i + 1
else
current_item = line_items.build(product_id: product_id)
end
current_item
end
def total_price
line_items.to_a.sum { |item| item.total_price }
end
end
Model of LineItem
class LineItem < ActiveRecord::Base
belongs_to :product
belongs_to :cart
validates :product_id, presence: true
validates :cart_id, presence: true
def total_price
product.price * quantity
end
end
View Carts #Show
<% if notice %>
<%= notice %>
<p id="notice"><%= notice %></p>
<% end %>
<h2>Your Cart </h2>
<table>
<% @cart.line_items.each do |item| %>
<tr>
<td><%= item.quantity %>×</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>
<%= link_to 'Empty cart', @cart, method: :delete, data: { confirm: 'Are you sure?' } %>
def destroy @line_item.destroy respond_to do |format| format.html { redirect_to line_items_url, notice: 'Line item was successfully destroyed.' } format.json { head :no_content } end end
private
# Use callbacks to share common setup or constraints between actions.
def set_line_item
@line_item = LineItem.find(params[:product_id])
end
end
# Never trust parameters from the scary internet, only allow the white list through.
def line_item_params
params.require(:line_item).permit(:product_id)
end
Controller Card
def create
@cart = Cart.new(cart_params)
respond_to do |format|
if @cart.save
format.html { redirect_to @cart, notice: 'Cart was successfully created.' }
format.json { render :show, status: :created, location: @cart }
else
format.html { render :new }
format.json { render json: @cart.errors, status: :unprocessable_entity }
end
end
end
Cart Controller destroy
def destroy
@cart.destroy if @cart.id == session[:cart_id]
session[:cart_id] = nil
respond_to do |format|
format.html { redirect_to store_url, notice: 'Your cart is currently empty.' }
format.json { head :no_content }
end
end
My db
class AddQuantityToLineItems < ActiveRecord::Migration
def change
add_column :line_items, :quantity, :integer, default: 0
end
end
session[:cart_id]
instead ofparams[:id]
. Am I right? – Alejandro Babio