Agile Web Development with Rails, Edition 5

9.3 Iteration D3: Adding a button 9.1 Iteration D1: Finding a Cart

9.2 Iteration D2: Connecting Products to Carts

Create line item which connects products to carts'

Create the model object.

rails generate scaffold LineItem product:references cart:belongs_to
      invoke  active_record
      create    db/migrate/20171113144102_create_line_items.rb
      create    app/models/line_item.rb
      invoke    test_unit
      create      test/models/line_item_test.rb
      create      test/fixtures/line_items.yml
      invoke  resource_route
       route    resources :line_items
      invoke  scaffold_controller
      create    app/controllers/line_items_controller.rb
      invoke    erb
      create      app/views/line_items
      create      app/views/line_items/index.html.erb
      create      app/views/line_items/edit.html.erb
      create      app/views/line_items/show.html.erb
      create      app/views/line_items/new.html.erb
      create      app/views/line_items/_form.html.erb
      invoke    test_unit
      create      test/controllers/line_items_controller_test.rb
      create      test/system/line_items_test.rb
      invoke    helper
      create      app/helpers/line_items_helper.rb
      invoke      test_unit
      invoke    jbuilder
      create      app/views/line_items/index.json.jbuilder
      create      app/views/line_items/show.json.jbuilder
      create      app/views/line_items/_line_item.json.jbuilder
      invoke  assets
      invoke    coffee
      create      app/assets/javascripts/
      invoke    scss
      create      app/assets/stylesheets/line_items.scss
      invoke  scss
   identical    app/assets/stylesheets/scaffolds.scss
rails db:migrate
mv 20171113144102_create_line_items.rb 20171113000003_create_line_items.rb
== 20171113000003 CreateLineItems: migrating ==================================
-- create_table(:line_items)
   -> 0.0016s
== 20171113000003 CreateLineItems: migrated (0.0016s) =========================

Cart has many line items.

edit app/models/cart.rb
class Cart < ApplicationRecord
  has_many :line_items, dependent: :destroy

Product has many line items.

edit app/models/product.rb
class Product < ApplicationRecord
  has_many :line_items
  before_destroy :ensure_not_referenced_by_any_line_item
    # ensure that there are no line items referencing this product
    def ensure_not_referenced_by_any_line_item
      unless line_items.empty?
        errors.add(:base, 'Line Items present')
        throw :abort

Line item belongs to both Cart and Product (But slightly more to the Cart). Also provide convenient access to the total price of the line item

edit app/models/line_item.rb
class LineItem < ApplicationRecord
  belongs_to :product
  belongs_to :cart

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 product_url(products(:two))
    assert_redirected_to products_url
  test "should destroy product" do
    assert_difference('Product.count', -1) do
      delete product_url(@product)
    assert_redirected_to products_url

change fixture so that product two is in both carts

edit test/fixtures/line_items.yml
# Read about fixtures at
  product: two
  cart: one
  product: two
  cart: two
rails test:controllers
Run options: --seed 60691
# Running:
Finished in 0.437990s, 52.5126 runs/s, 77.6273 assertions/s.
23 runs, 34 assertions, 0 failures, 0 errors, 0 skips

9.3 Iteration D3: Adding a button 9.1 Iteration D1: Finding a Cart