Agile Web Development with Rails, Edition 4

11.1 Iteration F1: Moving the Cart 10.3 Iteration E3: Finishing the Cart

10.4 Playtime

30 (tests|runs), 75 assertions, 0 failures, 0 errors.
<0> expected to be
>=
<1>.

Traceback:
  /home/rubys/git/awdwr/edition4/checkdepot.rb:36:in `assert_test_summary'
  /home/rubys/git/awdwr/edition4/checkdepot.rb:195:in `block in <class:DepotTest>'

Once again, get the tests working, and add tests for the smarter cart.

See that the tests fail.

rake test
DEPRECATION WARNING: alias_method_chain is deprecated. Please, use Module#prepend instead. From module, you can access the original method using super. (called from rescue in <class:Exception> at /home/rubys/.rvm/gems/ruby-head-n50123/gems/web-console-2.1.2/lib/web_console/integration/cruby.rb:37)
DEPRECATION WARNING: alias_method_chain is deprecated. Please, use Module#prepend instead. From module, you can access the original method using super. (called from block in <top (required)> at /home/rubys/.rvm/gems/ruby-head-n50123/gems/web-console-2.1.2/lib/web_console/extensions.rb:18)
DEPRECATION WARNING: alias_method_chain is deprecated. Please, use Module#prepend instead. From module, you can access the original method using super. (called from included at /home/rubys/.rvm/gems/ruby-head-n50123/gems/turbolinks-2.5.3/lib/turbolinks/xhr_url_for.rb:7)
rake aborted!
SyntaxError: /home/rubys/git/awdwr/edition4/work-220/depot/test/controllers/line_items_controller_test.rb:25: syntax error, unexpected keyword_end, expecting '}'
/home/rubys/git/awdwr/edition4/work-220/depot/test/controllers/line_items_controller_test.rb:59: syntax error, unexpected end-of-input, expecting keyword_end
/home/rubys/git/rails/activesupport/lib/active_support/dependencies.rb:274:in `require'
/home/rubys/git/rails/activesupport/lib/active_support/dependencies.rb:274:in `block in require'
/home/rubys/git/rails/activesupport/lib/active_support/dependencies.rb:240:in `load_dependency'
/home/rubys/git/rails/activesupport/lib/active_support/dependencies.rb:274:in `require'
/home/rubys/git/rails/railties/lib/rails/test_unit/runner.rb:118:in `block in run_tests'
/home/rubys/git/rails/railties/lib/rails/test_unit/runner.rb:117:in `each'
/home/rubys/git/rails/railties/lib/rails/test_unit/runner.rb:117:in `run_tests'
/home/rubys/git/rails/railties/lib/rails/test_unit/runner.rb:88:in `run'
/home/rubys/git/rails/railties/lib/rails/test_unit/runner.rb:82:in `run'
/home/rubys/git/rails/railties/lib/rails/test_unit/testing.rake:9:in `block in <top (required)>'
Tasks: TOP => test
(See full trace by running task with --trace)

Substitute names of products and carts for numbers

edit test/fixtures/line_items.yml
# Read about fixtures at
# http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
 
one:
  product: ruby
  cart: one
 
two:
  product: ruby
  cart: one

Update expected target of redirect: Cart#destroy.

edit test/controllers/carts_controller_test.rb
  test "should destroy cart" do
    assert_difference('Cart.count', -1) do
      session[:cart_id] = @cart.id
      delete :destroy, params: { id: @cart }
    end
 
    assert_redirected_to store_path
  end

Test both unique and duplicate products.

edit test/models/cart_test.rb
require 'test_helper'
 
class CartTest < ActiveSupport::TestCase
  test "add unique products" do
    cart = Cart.create
    book_one = products(:one)
    book_two  = products(:two)
    cart.add_product(book_one.id).save!
    cart.add_product(book_two.id).save!
    assert_equal 2, cart.line_items.size
    assert_equal book_one.price + book_two.price, cart.total_price
  end
  
  test "add_duplicate_product" do
    cart = Cart.create
    ruby_book = products(:ruby)
    cart.add_product(ruby_book.id).save!
    cart.add_product(ruby_book.id).save!
    assert_equal 2*book_one.price, cart.total_price
    assert_equal 1, cart.line_items.size
    assert_equal 2, cart.line_items[0].quantity
  end 
end
rake test test/models/cart_test.rb
DEPRECATION WARNING: alias_method_chain is deprecated. Please, use Module#prepend instead. From module, you can access the original method using super. (called from rescue in <class:Exception> at /home/rubys/.rvm/gems/ruby-head-n50123/gems/web-console-2.1.2/lib/web_console/integration/cruby.rb:37)
DEPRECATION WARNING: alias_method_chain is deprecated. Please, use Module#prepend instead. From module, you can access the original method using super. (called from block in <top (required)> at /home/rubys/.rvm/gems/ruby-head-n50123/gems/web-console-2.1.2/lib/web_console/extensions.rb:18)
DEPRECATION WARNING: alias_method_chain is deprecated. Please, use Module#prepend instead. From module, you can access the original method using super. (called from included at /home/rubys/.rvm/gems/ruby-head-n50123/gems/turbolinks-2.5.3/lib/turbolinks/xhr_url_for.rb:7)
Run options: --seed 6450
 
# Running:
 
.E
 
Finished in 0.085036s, 23.5194 runs/s, 23.5194 assertions/s.
 
  1) Error:
CartTest#test_add_duplicate_product:
NameError: undefined local variable or method `book_one' for #<CartTest:0x000000028ec6d0>
    test/models/cart_test.rb:24:in `block in <class:CartTest>'
 
2 runs, 2 assertions, 0 failures, 1 errors, 0 skips
 
Failed tests:
 
bin/rails test /home/rubys/git/awdwr/edition4/work-220/depot/test/models/cart_test.rb:19

Refactor.

edit test/models/cart_test.rb
require 'test_helper'
 
class CartTest < ActiveSupport::TestCase
  def setup
    @cart  = Cart.create
    @book_one = products(:ruby)
    @book_two  = products(:two)
  end
  
  test "add unique products" do
    @cart.add_product(@book_one.id).save!
    @cart.add_product(@book_two.id).save!
    assert_equal 2, @cart.line_items.size
    assert_equal @book_one.price + @book_two.price, @cart.total_price
  end
 
  test "add duplicate product" do
    @cart.add_product(@book_one.id).save!
    @cart.add_product(@book_one.id).save!
    assert_equal 2*@book_one.price, @cart.total_price
    assert_equal 1, @cart.line_items.size
    assert_equal 2, @cart.line_items[0].quantity
  end 
end
rake test test/models/cart_test.rb
DEPRECATION WARNING: alias_method_chain is deprecated. Please, use Module#prepend instead. From module, you can access the original method using super. (called from rescue in <class:Exception> at /home/rubys/.rvm/gems/ruby-head-n50123/gems/web-console-2.1.2/lib/web_console/integration/cruby.rb:37)
DEPRECATION WARNING: alias_method_chain is deprecated. Please, use Module#prepend instead. From module, you can access the original method using super. (called from block in <top (required)> at /home/rubys/.rvm/gems/ruby-head-n50123/gems/web-console-2.1.2/lib/web_console/extensions.rb:18)
DEPRECATION WARNING: alias_method_chain is deprecated. Please, use Module#prepend instead. From module, you can access the original method using super. (called from included at /home/rubys/.rvm/gems/ruby-head-n50123/gems/turbolinks-2.5.3/lib/turbolinks/xhr_url_for.rb:7)
Run options: --seed 38272
 
# Running:
 
..
 
Finished in 0.081800s, 24.4498 runs/s, 61.1245 assertions/s.
 
2 runs, 5 assertions, 0 failures, 0 errors, 0 skips

Verify that the tests pass.

rake test
DEPRECATION WARNING: alias_method_chain is deprecated. Please, use Module#prepend instead. From module, you can access the original method using super. (called from rescue in <class:Exception> at /home/rubys/.rvm/gems/ruby-head-n50123/gems/web-console-2.1.2/lib/web_console/integration/cruby.rb:37)
DEPRECATION WARNING: alias_method_chain is deprecated. Please, use Module#prepend instead. From module, you can access the original method using super. (called from block in <top (required)> at /home/rubys/.rvm/gems/ruby-head-n50123/gems/web-console-2.1.2/lib/web_console/extensions.rb:18)
DEPRECATION WARNING: alias_method_chain is deprecated. Please, use Module#prepend instead. From module, you can access the original method using super. (called from included at /home/rubys/.rvm/gems/ruby-head-n50123/gems/turbolinks-2.5.3/lib/turbolinks/xhr_url_for.rb:7)
rake aborted!
SyntaxError: /home/rubys/git/awdwr/edition4/work-220/depot/test/controllers/line_items_controller_test.rb:25: syntax error, unexpected keyword_end, expecting '}'
/home/rubys/git/awdwr/edition4/work-220/depot/test/controllers/line_items_controller_test.rb:59: syntax error, unexpected end-of-input, expecting keyword_end
/home/rubys/git/rails/activesupport/lib/active_support/dependencies.rb:274:in `require'
/home/rubys/git/rails/activesupport/lib/active_support/dependencies.rb:274:in `block in require'
/home/rubys/git/rails/activesupport/lib/active_support/dependencies.rb:240:in `load_dependency'
/home/rubys/git/rails/activesupport/lib/active_support/dependencies.rb:274:in `require'
/home/rubys/git/rails/railties/lib/rails/test_unit/runner.rb:118:in `block in run_tests'
/home/rubys/git/rails/railties/lib/rails/test_unit/runner.rb:117:in `each'
/home/rubys/git/rails/railties/lib/rails/test_unit/runner.rb:117:in `run_tests'
/home/rubys/git/rails/railties/lib/rails/test_unit/runner.rb:88:in `run'
/home/rubys/git/rails/railties/lib/rails/test_unit/runner.rb:82:in `run'
/home/rubys/git/rails/railties/lib/rails/test_unit/testing.rake:9:in `block in <top (required)>'
Tasks: TOP => test
(See full trace by running task with --trace)

Add a test ensuring that non-empty carts can't be deleted.

edit test/controllers/products_controller_test.rb
  test "can't delete product in cart" do
    assert_difference('Product.count', 0) do
      delete :destroy, params: { id: products(:ruby) }
    end
 
    assert_redirected_to products_path
  end
 
  test "should destroy product" do
    assert_difference('Product.count', -1) do
      delete :destroy, params: { id: @product }
    end
 
    assert_redirected_to products_path
  end

Now the tests should pass.

rake test
DEPRECATION WARNING: alias_method_chain is deprecated. Please, use Module#prepend instead. From module, you can access the original method using super. (called from rescue in <class:Exception> at /home/rubys/.rvm/gems/ruby-head-n50123/gems/web-console-2.1.2/lib/web_console/integration/cruby.rb:37)
DEPRECATION WARNING: alias_method_chain is deprecated. Please, use Module#prepend instead. From module, you can access the original method using super. (called from block in <top (required)> at /home/rubys/.rvm/gems/ruby-head-n50123/gems/web-console-2.1.2/lib/web_console/extensions.rb:18)
DEPRECATION WARNING: alias_method_chain is deprecated. Please, use Module#prepend instead. From module, you can access the original method using super. (called from included at /home/rubys/.rvm/gems/ruby-head-n50123/gems/turbolinks-2.5.3/lib/turbolinks/xhr_url_for.rb:7)
rake aborted!
SyntaxError: /home/rubys/git/awdwr/edition4/work-220/depot/test/controllers/line_items_controller_test.rb:25: syntax error, unexpected keyword_end, expecting '}'
/home/rubys/git/awdwr/edition4/work-220/depot/test/controllers/line_items_controller_test.rb:59: syntax error, unexpected end-of-input, expecting keyword_end
/home/rubys/git/rails/activesupport/lib/active_support/dependencies.rb:274:in `require'
/home/rubys/git/rails/activesupport/lib/active_support/dependencies.rb:274:in `block in require'
/home/rubys/git/rails/activesupport/lib/active_support/dependencies.rb:240:in `load_dependency'
/home/rubys/git/rails/activesupport/lib/active_support/dependencies.rb:274:in `require'
/home/rubys/git/rails/railties/lib/rails/test_unit/runner.rb:118:in `block in run_tests'
/home/rubys/git/rails/railties/lib/rails/test_unit/runner.rb:117:in `each'
/home/rubys/git/rails/railties/lib/rails/test_unit/runner.rb:117:in `run_tests'
/home/rubys/git/rails/railties/lib/rails/test_unit/runner.rb:88:in `run'
/home/rubys/git/rails/railties/lib/rails/test_unit/runner.rb:82:in `run'
/home/rubys/git/rails/railties/lib/rails/test_unit/testing.rake:9:in `block in <top (required)>'
Tasks: TOP => test
(See full trace by running task with --trace)

Add price to line item

rails generate migration add_price_to_line_item price:decimal
DEPRECATION WARNING: alias_method_chain is deprecated. Please, use Module#prepend instead. From module, you can access the original method using super. (called from rescue in <class:Exception> at /home/rubys/.rvm/gems/ruby-head-n50123/gems/web-console-2.1.2/lib/web_console/integration/cruby.rb:37)
      invoke  active_record
      create    db/migrate/20150330104541_add_price_to_line_item.rb
edit db/migrate/20150330104541_add_price_to_line_item.rb
class AddPriceToLineItem < ActiveRecord::Migration
  def change
    add_column :line_items, :price, :decimal
    LineItem.all.each do |li|
      li.price = li.product.price
    end
  end
end
rake db:migrate
mv 20150330104541_add_price_to_line_item.rb 20150330000006_add_price_to_line_item.rb
DEPRECATION WARNING: alias_method_chain is deprecated. Please, use Module#prepend instead. From module, you can access the original method using super. (called from rescue in <class:Exception> at /home/rubys/.rvm/gems/ruby-head-n50123/gems/web-console-2.1.2/lib/web_console/integration/cruby.rb:37)
== 20150330000006 AddPriceToLineItem: migrating ===============================
-- add_column(:line_items, :price, :decimal)
   -> 0.0027s
== 20150330000006 AddPriceToLineItem: migrated (0.0222s) ======================
 
edit app/models/cart.rb
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 += 1
    else
      current_item = line_items.build(product_id: product_id)
      current_item.price = current_item.product.price
    end
    current_item
  end
 
  def total_price
    line_items.to_a.sum { |item| item.total_price }
  end
end
git commit -a -m "Adding a Cart"
[master 8e40e5f] Adding a Cart
 4 files changed, 61 insertions(+), 11 deletions(-)
git tag iteration-d

11.1 Iteration F1: Moving the Cart 10.3 Iteration E3: Finishing the Cart