Cart Creation
What we’ll coverUsing SessionsPublic, Private, and Protected Methods in RubyRelationships between modelsActive Record Callbacks & ValidationAdding a button to a pageMore Functional Testing
Generate a shopping cartrails generate scaffold cartNo foreign keys presentOnly one of the tables has a foreign keyNeed to recover the cart with every request
Rails SessionsBy default, session info stored in a browser session cookie (4k limit)Database or memcached also availableDon’t store data that can easily be outdatedSerialized ActiveRecordobjectsCryptographically signed but unencryptedDon’t store critical information solely in the session
Associate the cart with a sessionapp/controllers/application_controller.rbprivatedefcurrent_cartCart.find(session[:cart_id])rescue ActiveRecord::RecordNotFound  cart = Cart.create   session[:cart_id] = cart.id cart	end
Public, Private, & Protected MethodsDifferent from Java & C#Public methods can be invoked by anyone Private methods accessible by an object from a derived classProtected methods accessible by other objects & objects from derived classesInheritance doesn’t determine method visibilityPrivate & protected methods visible from subclasses
Storing items in the cartrails generate scaffold line_itemproduct_id:integercart_id:integerBy convention, singular of table name appended with “_id”Need to establish relationship in both the database and the modelModel declarations add ability to build and navigate the relationship
ActiveRecord relationshipsOne to Onehas_one :containedbelongs_to :containerOne to Manyhas_many :containedbelongs_to :containerTable with foreign keys has the ‘belongs_to’
Add Relationship Specifiersclass Cart < ActiveRecord::Basehas_many :line_items, :dependent => :destroyendclass LineItem < ActiveRecord::Basebelongs_to :productbelongs_to :cartendclass Product < ActiveRecord::Basehas_many :line_itemsend
What if we destroy a cart?Line_items dependent on cart:dependent => :destroy indicates that line_items are destroyed along with the cartdestroy involves ActiveRecord validation logic, delete only removes from the database
What if we destroy a product?Make sure it isn’t contained in a cart
ActiveRecord Callbacks & ValidationsCallbacks invoked before & after operationsFor example save, delete, create, validateCan view unformatted data in ‘before’ callbacksDates & CurrencyReturning the actual value ‘false’ stops the operationAdd a handler or define as a method
Add a buttonWon’t be creating a new controller or a new actionCreating an item in the cart, so use line_item controllerLooking at generated code in line_item_controller.rb, we’ll use the ‘Create’ action‘Create’ action called using HTTP Postbutton_to‘button label’,  ‘URL Path’, ‘HTML options’Add ‘_path’ to controller to get URL path (i.e. line_item_path)Pass in hash values to URL path as parametersid extracted from ActiveRecord objects passed inapp/views/store/index.html.erb<%= button_to ‘Add to Cart’, line_items_path(:product_id => product) %>
Modify line_item createBy default, create parameter is a serialized line_item object - params[:line_item]Create a line_item based on the product id and add it to the cart
Modify line_item create (cont.)app/controllers/line_items_controller.rb
Update the functional testtest/functional/line_items_controller_test.rbassigns() accesses instance variables in the controller being tested
Try it outhttp://localhost:3000/Cart scaffolding didn’t show any attributes of what was just added
Modify the viewapp/views/cart/show.html.erb<h2>Your Pragmatic Cart</h2><ul>   <% for item in @cart.line_items %>       <li><%= item.product.title %></li>   <% end %></ul>
Try it out (again)http://localhost:3000/Cart now shows what is containedNeed to show each item only once (next chapter)
HomeworkChange the view so that clicking on a book’s image will also add the product to the cartAdd a new session variable to record how many times the user accessed the store controller’s index actionAdd the counter to the template and display it on top of the catalog pageReset the counter to zero when adding to the cartChange template to display counter when > 5

Cart creation-101217222728-phpapp01

  • 1.
  • 2.
    What we’ll coverUsingSessionsPublic, Private, and Protected Methods in RubyRelationships between modelsActive Record Callbacks & ValidationAdding a button to a pageMore Functional Testing
  • 3.
    Generate a shoppingcartrails generate scaffold cartNo foreign keys presentOnly one of the tables has a foreign keyNeed to recover the cart with every request
  • 4.
    Rails SessionsBy default,session info stored in a browser session cookie (4k limit)Database or memcached also availableDon’t store data that can easily be outdatedSerialized ActiveRecordobjectsCryptographically signed but unencryptedDon’t store critical information solely in the session
  • 5.
    Associate the cartwith a sessionapp/controllers/application_controller.rbprivatedefcurrent_cartCart.find(session[:cart_id])rescue ActiveRecord::RecordNotFound cart = Cart.create session[:cart_id] = cart.id cart end
  • 6.
    Public, Private, &Protected MethodsDifferent from Java & C#Public methods can be invoked by anyone Private methods accessible by an object from a derived classProtected methods accessible by other objects & objects from derived classesInheritance doesn’t determine method visibilityPrivate & protected methods visible from subclasses
  • 7.
    Storing items inthe cartrails generate scaffold line_itemproduct_id:integercart_id:integerBy convention, singular of table name appended with “_id”Need to establish relationship in both the database and the modelModel declarations add ability to build and navigate the relationship
  • 8.
    ActiveRecord relationshipsOne toOnehas_one :containedbelongs_to :containerOne to Manyhas_many :containedbelongs_to :containerTable with foreign keys has the ‘belongs_to’
  • 9.
    Add Relationship SpecifiersclassCart < ActiveRecord::Basehas_many :line_items, :dependent => :destroyendclass LineItem < ActiveRecord::Basebelongs_to :productbelongs_to :cartendclass Product < ActiveRecord::Basehas_many :line_itemsend
  • 10.
    What if wedestroy a cart?Line_items dependent on cart:dependent => :destroy indicates that line_items are destroyed along with the cartdestroy involves ActiveRecord validation logic, delete only removes from the database
  • 11.
    What if wedestroy a product?Make sure it isn’t contained in a cart
  • 12.
    ActiveRecord Callbacks &ValidationsCallbacks invoked before & after operationsFor example save, delete, create, validateCan view unformatted data in ‘before’ callbacksDates & CurrencyReturning the actual value ‘false’ stops the operationAdd a handler or define as a method
  • 13.
    Add a buttonWon’tbe creating a new controller or a new actionCreating an item in the cart, so use line_item controllerLooking at generated code in line_item_controller.rb, we’ll use the ‘Create’ action‘Create’ action called using HTTP Postbutton_to‘button label’, ‘URL Path’, ‘HTML options’Add ‘_path’ to controller to get URL path (i.e. line_item_path)Pass in hash values to URL path as parametersid extracted from ActiveRecord objects passed inapp/views/store/index.html.erb<%= button_to ‘Add to Cart’, line_items_path(:product_id => product) %>
  • 14.
    Modify line_item createBydefault, create parameter is a serialized line_item object - params[:line_item]Create a line_item based on the product id and add it to the cart
  • 15.
    Modify line_item create(cont.)app/controllers/line_items_controller.rb
  • 16.
    Update the functionaltesttest/functional/line_items_controller_test.rbassigns() accesses instance variables in the controller being tested
  • 17.
    Try it outhttp://localhost:3000/Cartscaffolding didn’t show any attributes of what was just added
  • 18.
    Modify the viewapp/views/cart/show.html.erb<h2>YourPragmatic Cart</h2><ul> <% for item in @cart.line_items %> <li><%= item.product.title %></li> <% end %></ul>
  • 19.
    Try it out(again)http://localhost:3000/Cart now shows what is containedNeed to show each item only once (next chapter)
  • 20.
    HomeworkChange the viewso that clicking on a book’s image will also add the product to the cartAdd a new session variable to record how many times the user accessed the store controller’s index actionAdd the counter to the template and display it on top of the catalog pageReset the counter to zero when adding to the cartChange template to display counter when > 5

Editor's Notes

  • #6 - current_cart available to all controllers‘create’ an ActiveRecord method that creates &amp; stores in the databaseas an aside, ‘private’ will look wrong to those from a Java or C# background
  • #9 Other relationships are available - Many to Many - Relationships through a 3rd model
  • #10 Can do things like li = LineItem.find(…) puts “This is for #{li.product.title}”Cart can reference its collection cart.line_items.count
  • #12 Use an ActiveRecord callback to perform validation
  • #13 - Unformatted data in validation callback
  • #14 Links use HTTP GET, Buttons use HTTP POSTbutton_to uses &lt;form&gt; and &lt;div&gt; elements which drop down to another line unless made inline with CSS
  • #16 ActiveRecord ‘build’ allows you to add an object to the collection with references set
  • #17 - Updatetest to reflect changes in the controller- In the “real world”, we would update the test first- rake test:functionals