11.1 Iteration F1: Moving the Cart 10.3 Iteration E3: Finishing the Cart
Once again, get the tests working, and add tests for the smarter cart.
See that the tests fail.
rake test
[deprecated] I18n.enforce_available_locales will default to true in the future. If you really want to skip validation of your locale you can set I18n.enforce_available_locales = false to avoid this message.
[deprecated] I18n.enforce_available_locales will default to true in the future. If you really want to skip validation of your locale you can set I18n.enforce_available_locales = false to avoid this message.
Loaded suite /home/rubys/.rvm/gems/ruby-1.9.2-p320/gems/rake-10.1.1/lib/rake/rake_test_loader
Started
ProductTest:
PASS image url (0.26s)
PASS product attributes must not be empty (0.00s)
PASS product is not valid without a unique title (0.00s)
PASS product is not valid without a unique title - i18n (0.00s)
PASS product price must be positive (0.00s)
Finished in 0.278930 seconds.
5 tests, 23 assertions, 0 failures, 0 errors, 0 skips
[deprecated] I18n.enforce_available_locales will default to true in the future. If you really want to skip validation of your locale you can set I18n.enforce_available_locales = false to avoid this message.
Loaded suite /home/rubys/.rvm/gems/ruby-1.9.2-p320/gems/rake-10.1.1/lib/rake/rake_test_loader
Started
CartsControllerTest:
PASS should create cart (0.19s)
FAIL should destroy cart (0.04s)
"Cart.count" didn't change by -1.
<1> expected but was
<2>.
/home/rubys/git/rails/activesupport/lib/active_support/testing/assertions.rb:60:in `block in assert_difference'
PASS should get edit (0.06s)
PASS should get index (0.01s)
PASS should get new (0.01s)
PASS should show cart (0.01s)
PASS should update cart (0.01s)
LineItemsControllerTest:
PASS should create line item (0.03s)
PASS should destroy line item (0.01s)
PASS should get edit (0.04s)
PASS should get index (0.01s)
PASS should get new (0.01s)
PASS should show line item (0.01s)
PASS should update line item (0.01s)
ProductsControllerTest:
PASS should create product (0.02s)
PASS should destroy product (0.01s)
PASS should get edit (0.01s)
PASS should get index (0.04s)
PASS should get new (0.01s)
PASS should show product (0.01s)
PASS should update product (0.01s)
StoreControllerTest:
PASS should get index (0.05s)
Finished in 0.581573 seconds.
22 tests, 34 assertions, 1 failures, 0 errors, 0 skips
Errors running test:functionals!
Substitute names of products and carts for numbers
edit test/fixtures/line_items.yml
# Read about fixtures at
# http://api.rubyonrails.org/classes/ActiveRecord/Fixtures.html
one:
product: ruby
cart: one
two:
product: ruby
cart: one
Update expected target of redirect: Cart#destroy.
edit test/functional/carts_controller_test.rb
test "should destroy cart" do
assert_difference('Cart.count', -1) do
session[:cart_id] = @cart.id
delete :destroy, id: @cart.to_param
end
assert_redirected_to store_path
end
Test both unique and duplicate products.
edit test/unit/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
ruby -I test test/unit/cart_test.rb
[deprecated] I18n.enforce_available_locales will default to true in the future. If you really want to skip validation of your locale you can set I18n.enforce_available_locales = false to avoid this message.
Loaded suite test/unit/cart_test
Started
CartTest:
ERROR add duplicate product (0.28s)
NameError: undefined local variable or method `book_one' for #<CartTest:0x00000003bc1300>
test/unit/cart_test.rb:24:in `block in <class:CartTest>'
PASS add unique products (0.03s)
Finished in 0.321148 seconds.
2 tests, 2 assertions, 0 failures, 1 errors, 0 skips
Refactor.
edit test/unit/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
ruby -I test test/unit/cart_test.rb
[deprecated] I18n.enforce_available_locales will default to true in the future. If you really want to skip validation of your locale you can set I18n.enforce_available_locales = false to avoid this message.
Loaded suite test/unit/cart_test
Started
CartTest:
PASS add duplicate product (0.29s)
PASS add unique products (0.01s)
Finished in 0.304555 seconds.
2 tests, 5 assertions, 0 failures, 0 errors, 0 skips
Verify that the tests pass.
rake test
[deprecated] I18n.enforce_available_locales will default to true in the future. If you really want to skip validation of your locale you can set I18n.enforce_available_locales = false to avoid this message.
[deprecated] I18n.enforce_available_locales will default to true in the future. If you really want to skip validation of your locale you can set I18n.enforce_available_locales = false to avoid this message.
Loaded suite /home/rubys/.rvm/gems/ruby-1.9.2-p320/gems/rake-10.1.1/lib/rake/rake_test_loader
Started
CartTest:
PASS add duplicate product (0.23s)
PASS add unique products (0.01s)
ProductTest:
PASS image url (0.04s)
PASS product attributes must not be empty (0.00s)
PASS product is not valid without a unique title (0.00s)
PASS product is not valid without a unique title - i18n (0.00s)
PASS product price must be positive (0.00s)
Finished in 0.288348 seconds.
7 tests, 28 assertions, 0 failures, 0 errors, 0 skips
[deprecated] I18n.enforce_available_locales will default to true in the future. If you really want to skip validation of your locale you can set I18n.enforce_available_locales = false to avoid this message.
Loaded suite /home/rubys/.rvm/gems/ruby-1.9.2-p320/gems/rake-10.1.1/lib/rake/rake_test_loader
Started
CartsControllerTest:
PASS should create cart (0.23s)
PASS should destroy cart (0.07s)
PASS should get edit (0.04s)
PASS should get index (0.01s)
PASS should get new (0.01s)
PASS should show cart (0.02s)
PASS should update cart (0.01s)
LineItemsControllerTest:
PASS should create line item (0.01s)
PASS should destroy line item (0.00s)
PASS should get edit (0.03s)
PASS should get index (0.01s)
PASS should get new (0.01s)
PASS should show line item (0.01s)
PASS should update line item (0.01s)
ProductsControllerTest:
PASS should create product (0.02s)
PASS should destroy product (0.01s)
PASS should get edit (0.01s)
PASS should get index (0.04s)
PASS should get new (0.01s)
PASS should show product (0.01s)
PASS should update product (0.01s)
StoreControllerTest:
PASS should get index (0.05s)
Finished in 0.594886 seconds.
22 tests, 35 assertions, 0 failures, 0 errors, 0 skips
Add a test ensuring that non-empty carts can't be deleted.
edit test/functional/products_controller_test.rb
test "can't delete product in cart" do
assert_difference('Product.count', 0) do
delete :destroy, id: products(:ruby).to_param
end
assert_redirected_to products_path
end
test "should destroy product" do
assert_difference('Product.count', -1) do
delete :destroy, id: @product.to_param
end
assert_redirected_to products_path
end
Now the tests should pass.
rake test
[deprecated] I18n.enforce_available_locales will default to true in the future. If you really want to skip validation of your locale you can set I18n.enforce_available_locales = false to avoid this message.
[deprecated] I18n.enforce_available_locales will default to true in the future. If you really want to skip validation of your locale you can set I18n.enforce_available_locales = false to avoid this message.
Loaded suite /home/rubys/.rvm/gems/ruby-1.9.2-p320/gems/rake-10.1.1/lib/rake/rake_test_loader
Started
CartTest:
PASS add duplicate product (0.30s)
PASS add unique products (0.01s)
ProductTest:
PASS image url (0.04s)
PASS product attributes must not be empty (0.00s)
PASS product is not valid without a unique title (0.00s)
PASS product is not valid without a unique title - i18n (0.00s)
PASS product price must be positive (0.00s)
Finished in 0.366767 seconds.
7 tests, 28 assertions, 0 failures, 0 errors, 0 skips
[deprecated] I18n.enforce_available_locales will default to true in the future. If you really want to skip validation of your locale you can set I18n.enforce_available_locales = false to avoid this message.
Loaded suite /home/rubys/.rvm/gems/ruby-1.9.2-p320/gems/rake-10.1.1/lib/rake/rake_test_loader
Started
CartsControllerTest:
PASS should create cart (0.14s)
PASS should destroy cart (0.08s)
PASS should get edit (0.04s)
PASS should get index (0.01s)
PASS should get new (0.01s)
PASS should show cart (0.02s)
PASS should update cart (0.01s)
LineItemsControllerTest:
PASS should create line item (0.01s)
PASS should destroy line item (0.01s)
PASS should get edit (0.04s)
PASS should get index (0.01s)
PASS should get new (0.01s)
PASS should show line item (0.01s)
PASS should update line item (0.01s)
ProductsControllerTest:
PASS can't delete product in cart (0.01s)
PASS should create product (0.02s)
PASS should destroy product (0.01s)
PASS should get edit (0.01s)
PASS should get index (0.04s)
PASS should get new (0.01s)
PASS should show product (0.01s)
PASS should update product (0.01s)
StoreControllerTest:
PASS should get index (0.05s)
Finished in 0.549422 seconds.
23 tests, 37 assertions, 0 failures, 0 errors, 0 skips
Add price to line item
rails generate migration add_price_to_line_item price:decimal
[deprecated] I18n.enforce_available_locales will default to true in the future. If you really want to skip validation of your locale you can set I18n.enforce_available_locales = false to avoid this message.
invoke active_record
create db/migrate/20140204195921_add_price_to_line_item.rb
edit db/migrate/20140204195921_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 20140204195921_add_price_to_line_item.rb 20140204000006_add_price_to_line_item.rb
[deprecated] I18n.enforce_available_locales will default to true in the future. If you really want to skip validation of your locale you can set I18n.enforce_available_locales = false to avoid this message.
== AddPriceToLineItem: migrating =============================================
-- add_column(:line_items, :price, :decimal)
-> 0.0005s
== AddPriceToLineItem: migrated (0.1014s) ====================================
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 9ceb605] Adding a Cart
5 files changed, 72 insertions(+), 11 deletions(-)
git tag iteration-d
11.1 Iteration F1: Moving the Cart 10.3 Iteration E3: Finishing the Cart