Simple relationship

Create the application.

ruby -rubygems /home/rubys/git/rails/bin/rails new depot
      create  
      create  README
      create  Rakefile
      create  config.ru
      create  .gitignore
      create  Gemfile
      create  app
      create  app/controllers/application_controller.rb
      create  app/helpers/application_helper.rb
      create  app/mailers
      create  app/models
      create  app/views/layouts/application.html.erb
      create  config
      create  config/routes.rb
      create  config/application.rb
      create  config/environment.rb
      create  config/environments
      create  config/environments/development.rb
      create  config/environments/production.rb
      create  config/environments/test.rb
      create  config/initializers
      create  config/initializers/backtrace_silencers.rb
      create  config/initializers/inflections.rb
      create  config/initializers/mime_types.rb
      create  config/initializers/secret_token.rb
      create  config/initializers/session_store.rb
      create  config/locales
      create  config/locales/en.yml
      create  config/boot.rb
      create  config/database.yml
      create  db
      create  db/seeds.rb
      create  doc
      create  doc/README_FOR_APP
      create  lib
      create  lib/tasks
      create  lib/tasks/.gitkeep
      create  log
      create  log/server.log
      create  log/production.log
      create  log/development.log
      create  log/test.log
      create  public
      create  public/404.html
      create  public/422.html
      create  public/500.html
      create  public/favicon.ico
      create  public/index.html
      create  public/robots.txt
      create  public/images
      create  public/images/rails.png
      create  public/stylesheets
      create  public/stylesheets/.gitkeep
      create  public/javascripts
      create  public/javascripts/application.js
      create  public/javascripts/controls.js
      create  public/javascripts/dragdrop.js
      create  public/javascripts/effects.js
      create  public/javascripts/prototype.js
      create  public/javascripts/rails.js
      create  script
      create  script/rails
      create  test
      create  test/fixtures
      create  test/functional
      create  test/integration
      create  test/performance/browsing_test.rb
      create  test/test_helper.rb
      create  test/unit
      create  tmp
      create  tmp/sessions
      create  tmp/sockets
      create  tmp/cache
      create  tmp/pids
      create  vendor/plugins
      create  vendor/plugins/.gitkeep
bundle install
Using rake (0.8.7) 
Using abstract (1.0.0) 
Using activesupport (3.0.7) from source at /home/rubys/git/rails 
Using builder (2.1.2) 
Using i18n (0.5.0) 
Using activemodel (3.0.7) from source at /home/rubys/git/rails 
Using erubis (2.6.6) 
Using rack (1.2.2) 
Using rack-mount (0.6.14) 
Using rack-test (0.5.7) 
Using tzinfo (0.3.27) 
Using actionpack (3.0.7) from source at /home/rubys/git/rails 
Using mime-types (1.16) 
Using polyglot (0.3.1) 
Using treetop (1.4.9) 
Using mail (2.2.19) 
Using actionmailer (3.0.7) from source at /home/rubys/git/rails 
Using arel (2.0.9) 
Using activerecord (3.0.7) from source at /home/rubys/git/rails 
Using activeresource (3.0.7) from source at /home/rubys/git/rails 
Using bundler (1.0.12) 
Using thor (0.14.6) 
Using railties (3.0.7) from source at /home/rubys/git/rails 
Using rails (3.0.7) from source at /home/rubys/git/rails 
Using sqlite3 (1.3.3) 
Your bundle is complete! Use `bundle show [gemname]` to see where a bundled gem is installed.

Generating our first model and associated scaffolding

rails generate scaffold product title:string
      invoke  active_record
      create    db/migrate/20110509143208_create_products.rb
      create    app/models/product.rb
      invoke    test_unit
      create      test/unit/product_test.rb
      create      test/fixtures/products.yml
       route  resources :products
      invoke  scaffold_controller
      create    app/controllers/products_controller.rb
      invoke    erb
      create      app/views/products
      create      app/views/products/index.html.erb
      create      app/views/products/edit.html.erb
      create      app/views/products/show.html.erb
      create      app/views/products/new.html.erb
      create      app/views/products/_form.html.erb
      invoke    test_unit
      create      test/functional/products_controller_test.rb
      invoke    helper
      create      app/helpers/products_helper.rb
      invoke      test_unit
      create        test/unit/helpers/products_helper_test.rb
      invoke  stylesheets
      create    public/stylesheets/scaffold.css

Create a second controller with a single index action

rails generate controller store index
      create  app/controllers/store_controller.rb
       route  get "store/index"
      invoke  erb
      create    app/views/store
      create    app/views/store/index.html.erb
      invoke  test_unit
      create    test/functional/store_controller_test.rb
      invoke  helper
      create    app/helpers/store_helper.rb
      invoke    test_unit
      create      test/unit/helpers/store_helper_test.rb

Create a cart.

rails generate scaffold cart
      invoke  active_record
      create    db/migrate/20110509143209_create_carts.rb
      create    app/models/cart.rb
      invoke    test_unit
      create      test/unit/cart_test.rb
      create      test/fixtures/carts.yml
       route  resources :carts
      invoke  scaffold_controller
      create    app/controllers/carts_controller.rb
      invoke    erb
      create      app/views/carts
      create      app/views/carts/index.html.erb
      create      app/views/carts/edit.html.erb
      create      app/views/carts/show.html.erb
      create      app/views/carts/new.html.erb
      create      app/views/carts/_form.html.erb
      invoke    test_unit
      create      test/functional/carts_controller_test.rb
      invoke    helper
      create      app/helpers/carts_helper.rb
      invoke      test_unit
      create        test/unit/helpers/carts_helper_test.rb
      invoke  stylesheets
   identical    public/stylesheets/scaffold.css

Create an order.

rails generate scaffold order
      invoke  active_record
      create    db/migrate/20110509143210_create_orders.rb
      create    app/models/order.rb
      invoke    test_unit
      create      test/unit/order_test.rb
      create      test/fixtures/orders.yml
       route  resources :orders
      invoke  scaffold_controller
      create    app/controllers/orders_controller.rb
      invoke    erb
      create      app/views/orders
      create      app/views/orders/index.html.erb
      create      app/views/orders/edit.html.erb
      create      app/views/orders/show.html.erb
      create      app/views/orders/new.html.erb
      create      app/views/orders/_form.html.erb
      invoke    test_unit
      create      test/functional/orders_controller_test.rb
      invoke    helper
      create      app/helpers/orders_helper.rb
      invoke      test_unit
      create        test/unit/helpers/orders_helper_test.rb
      invoke  stylesheets
   identical    public/stylesheets/scaffold.css

Create the relationship object.

rails generate scaffold line_item product_id:integer cart_id:integer order_id:integer
      invoke  active_record
      create    db/migrate/20110509143211_create_line_items.rb
      create    app/models/line_item.rb
      invoke    test_unit
      create      test/unit/line_item_test.rb
      create      test/fixtures/line_items.yml
       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/functional/line_items_controller_test.rb
      invoke    helper
      create      app/helpers/line_items_helper.rb
      invoke      test_unit
      create        test/unit/helpers/line_items_helper_test.rb
      invoke  stylesheets
   identical    public/stylesheets/scaffold.css

Cart has many line items.

edit app/models/cart.rb
class Cart < ActiveRecord::Base
  has_many :line_items, :dependent=>:destroy
end

Order has many line items.

edit app/models/order.rb
class Order < ActiveRecord::Base
  has_many :line_items, :dependent=>:destroy
end

Product has many line items.

edit app/models/product.rb
class Product < ActiveRecord::Base
  has_many :line_items
end

Line item belongs to both Product and either a Cart or Order

edit app/models/line_item.rb
class LineItem < ActiveRecord::Base
  belongs_to :product
  belongs_to :cart
  belongs_to :order
end

Custom logic for creating a cart from an order

edit app/controllers/orders_controller.rb
  def create
    cart = Cart.find_by_id(params[:cart_id])
    @order = Order.new(params[:order])
 
    # move line items from cart to order
    cart.line_items.each do |item|
      item.cart_id = nil
      @order.line_items << item
    end
 
    respond_to do |format|
      if @order.save
        Cart.destroy(params[:cart_id])
        format.html { redirect_to(@order, :notice => 'Order was successfully created.') }
        format.xml  { render :xml => @order, :status => :created, :location => @order }
      else
        format.html { render :action => "new" }
        format.xml  { render :xml => @order.errors, :status => :unprocessable_entity }
      end
    end
  end
rake db:migrate
mv 20110509143208_create_products.rb 20110211000001_create_products.rb
mv 20110509143209_create_carts.rb 20110211000002_create_carts.rb
mv 20110509143210_create_orders.rb 20110211000003_create_orders.rb
mv 20110509143211_create_line_items.rb 20110211000004_create_line_items.rb
(in /home/rubys/tmp/work-30/depot)
==  CreateProducts: migrating =================================================
-- create_table(:products)
   -> 0.0015s
==  CreateProducts: migrated (0.0016s) ========================================
 
==  CreateCarts: migrating ====================================================
-- create_table(:carts)
   -> 0.0012s
==  CreateCarts: migrated (0.0013s) ===========================================
 
==  CreateOrders: migrating ===================================================
-- create_table(:orders)
   -> 0.0012s
==  CreateOrders: migrated (0.0013s) ==========================================
 
==  CreateLineItems: migrating ================================================
-- create_table(:line_items)
   -> 0.0017s
==  CreateLineItems: migrated (0.0018s) =======================================
 

Start the server.

Create a product

get /products/new

New product


Back
post /products
  • product[title] => Pragmatic Version Control
You are being redirected.
get http://localhost:3000/products/1

Product was successfully created.

Title: Pragmatic Version Control

Edit | Back

Create a cart

get /carts/new

New cart

Back
post /carts
You are being redirected.
get http://localhost:3000/carts/1

Cart was successfully created.

Edit | Back

Connect the two

get /line_items/new

New line_item




Back
post /line_items
  • line_item[cart_id] => 1
  • line_item[product_id] => 1
You are being redirected.
get http://localhost:3000/line_items/1

Line item was successfully created.

Product: 1

Cart: 1

Order:

Edit | Back

Show the line item

sqlite3> select * from line_items
        id = 1
product_id = 1
   cart_id = 1
  order_id = 
created_at = 2011-05-09 14:32:21.504287
updated_at = 2011-05-09 14:32:21.504287

Create an order from a cart

post /orders
  • cart_id => 1
You are being redirected.
get http://localhost:3000/orders/1

Order was successfully created.

Edit | Back

Show the line item

sqlite3> select * from line_items
        id = 1
product_id = 1
   cart_id = 
  order_id = 1
created_at = 2011-05-09 14:32:21.504287
updated_at = 2011-05-09 14:32:21.980281

Environment

Mon, 09 May 2011 14:32:22 GMT
echo $PATH
/home/rubys/.rvm/gems/ruby-1.8.7-p334/bin:/home/rubys/.rvm/gems/ruby-1.8.7-p334@global/bin:/home/rubys/.rvm/rubies/ruby-1.8.7-p334/bin:/home/rubys/.rvm/bin:/home/rubys/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
node -v
v0.2.6
/home/rubys/.rvm/rubies/ruby-1.8.7-p334/bin/ruby -v
ruby 1.8.7 (2011-02-18 patchlevel 334) [x86_64-linux]
gem -v
1.6.2
bundle show
Gems included by the bundle:
  * abstract (1.0.0)
  * actionmailer (3.0.7)
  * actionpack (3.0.7)
  * activemodel (3.0.7)
  * activerecord (3.0.7)
  * activeresource (3.0.7)
  * activesupport (3.0.7)
  * arel (2.0.9)
  * builder (2.1.2)
  * bundler (1.0.12)
  * erubis (2.6.6)
  * i18n (0.5.0)
  * mail (2.2.19)
  * mime-types (1.16)
  * polyglot (0.3.1)
  * rack (1.2.2)
  * rack-mount (0.6.14)
  * rack-test (0.5.7)
  * rails (3.0.7 9575db6)
  * railties (3.0.7)
  * rake (0.8.7)
  * sqlite3 (1.3.3)
  * thor (0.14.6)
  * treetop (1.4.9)
  * tzinfo (0.3.27)
rake about
(in /home/rubys/tmp/work-30/depot)
About your application's environment
Ruby version              1.8.7 (x86_64-linux)
RubyGems version          1.6.2
Rack version              1.2
Rails version             3.0.7
Active Record version     3.0.7
Action Pack version       3.0.7
Active Resource version   3.0.7
Action Mailer version     3.0.7
Active Support version    3.0.7
Application root          /home/rubys/tmp/work-30/depot
Environment               development
git log -1
commit 9575db644396af54fd60f92eb8f81997b3e46941
Author: José Valim <jose.valim@gmail.com>
Date:   Fri May 6 18:42:06 2011 +0200

    Revert "Pass the proper method_name instead of hardcoding to action_name."
    
    This commit was actually correct. The first parameter in process_action
    is not necessarily the same as the action_name. Use action_name to
    retrieve the action instead.
    
    This reverts commit 4e2bacdf7cbece8225552e64358fb53ad6b70540.