Sessions Carol Wolf Computer Science HTTP – Hypertext Transfer Protocol Protocol may refer to: (from Wikipedia) Protocol (diplomacy), the etiquette of diplomacy and affairs of state Protocol (politics), a formal agreement between nation states Protocol, a.k.a. etiquette Clinical protocol, a.k.a. guideline (medical) Research methods: Protocol (natural sciences) Clinical trial protocol Voice procedure a protocol for voice communications Protocol (object-oriented programming), a common means for unrelated objects to communicate with each other Communications protocol, in telecommunications and computer networking Protocol (band), British Protocol (film), a 1984 comedy film Protocol (album), the début album/EP from Simon Phillips HTTP A single web transaction consists of a request, service and response. Once the transaction is finished, the server does not retain any memory of it. A standard solution is to store some information about the transaction in a cookie on the user’s computer. This is usually an id. It is important that no two users get assigned the same id. Web sites with heavy traffic can use GUIDs. A GUID is a Global Unique IDentifier. Generally, a GUID consists of a random number created using the time on the computer in nanoseconds and some feature of the server. In the past this was the network card MAC (Media Access Control) address. But after the Melissa worm used this to infect computers world-wide, Microsoft changed the GUID algorithm. The string, 3F2504E0 4f89 11D3 9A 0C 03 05 E8 2C 33 01, is an example of a GUID. The numbers are in hexadecimal. This id is then stored in the session on the server. When a user returns, the id is obtained from the cookie in order to find the appropriate user (and usually the user’s cart). The Rails Session Web application frameworks all come with sessions. In Rails, the information in the session is stored in a hash. The size limit is 4K, so usually only an id is stored. And the id is most often a shopping cart id. The following example will be a student registration example. Given a list of courses, a student can choose the courses he/she wishes to take and collect them in a cart. When done the student would have to log into his/her university account. The index page Files generated Generate the courses table rails generate scaffold course number:string name:string credits:integer Generate the carts table. Carts are only needed for their ids. rails generate scaffold cart Generate the choices table rails generate scaffold choice cart_id:integer course_id:integer Create the tables with rake db:migrate Add some courses to the courses table to use as examples. The cart The cart id will be stored in the session and then used by the choices table. This is done in the application controller. class ApplicationController < ActionController::Base protect_from_forgery private def current_cart Cart.find(session[:cart_id]) #See if a cart already exists. rescue ActiveRecord::RecordNotFound #If not, create a new one. cart = Cart.create session[:cart_id] = cart.id #Store the cart id in the session hash. cart # return the cart end end The choices table The choices table is used to connect the student (via the cart) to the courses. Connections are made using belongs_to. class Choice < ActiveRecord::Base #In the model folder belongs_to :course belongs_to :cart #The credits method is used to return the credits for the chosen course. def credits course.credits end end On course can be chosen by many students. All operations on the model (table) will be ordered by number. class Course < ActiveRecord::Base default_scope :order => 'number' has_many :choices validates :number, :name, :credits, :presence => true validates :credits, :numericality => {:greater_than_or_equal_to => 1} validates :number, :uniqueness => true end The Cart class class Cart < ActiveRecord::Base has_many :choices, :dependent => :destroy def add_course(course_id) current_choice = choices.where(:course_id => course_id).first #If the course has not been chosen already, create a new choice. if current_choice == nil current_choice = Choice.new(:course_id => course_id) choices << current_choice # Append the new choice to choices. end current_choice #return value end def total_credits #Used to add up the credits chosen so far. choices.to_a.sum { |list| list.credits} #to_a makes an array of the choices. end end The cart class The cart class connects to the choices table. When the cart is emptied, all dependent records will also be removed. The cart class is used to add a course to the choices table. This requires both the cart id (representing the student) and the course id. If the cart_id/course_id combination is not in the choices table, the new record is added. If it is, nothing is done. In either case, the record is returned. The total_credits method is used to keep track of the number of credits already in the cart. View to change Change the list_courses view <% @courses.each do |course| %> <tr> <td><%= course.number %></td> <td><%= course.name %></td> <td><%= course.credits %></td> <td><%= button_to "Add Course to Schedule", choices_path(:course_id => course.id) %> </tr> <% end %> Add the button to the table. This sends the id of the chosen course to the choices controller. Choices controller – create method def create @cart = current_cart # found in application controller course = Course.find(params[:course_id]) current_choice = Choice.find_by_course_id(course.id) if current_choice == nil # This is a new addition. @choice = @cart.add_course(course.id) respond_to do |format| if @choice.save format.html { redirect_to(@choice.cart, :notice => 'Course was successfully added.') } else format.html { render :action => "new" } end end Choices controller – create method (more) else @choice = current_choice respond_to do |format| format.html {redirect_to(@choice.cart, :notice => 'Course was a duplicate and not added.') } end end end Choices controller – create method First the method gets the current cart’s id from the session using the application controller. It then uses the id it received from the web page parameters to find the course in the choices table. If this course, the current_choice, has not yet been added to the table, it now is and a notice is flashed to the user. If it is already in the cart, no changes are made and a notice to this effect is flashed back. In either case, control is redirected to the show web page in the views/carts folder. Show web page in views/carts folder <p id="notice"><%= notice %></p> <table> <% for item in @cart.choices %> <tr> <td><%= item.course.number %> </td> <td><%= item.course.name %></td> <td><%= item.course.credits %></td> </tr> <% end %> <tr> <td colspan="2">Total Credits</td> <td><%= @cart.total_credits %></td> </tr> </table> Show web page in views/carts folder # Add a button to empty the cart (and start over). <p><%= button_to "Empty Cart", @cart, :method => :delete, :confirm => 'Are you sure?' %></p> # Link back to the main page. <p><%= link_to 'Back', schedule_index_path %></p> The show method will show the cart and allow a student to empty it and start over, if desired. Two versions of the show web page Emptying the cart – in views/carts Change one line in the delete method for the cart. def destroy @cart = Cart.find(params[:id]) @cart.destroy respond_to do |format| format.html { redirect_to(schedule_index_url) } format.xml { head :ok } end end