Home arrow Ruby-on-Rails arrow Page 4 - Controlling Information Access with the Rails Action Controller
RUBY-ON-RAILS

Controlling Information Access with the Rails Action Controller


In this conclusion to a four-part series on the Rails Action Controller, you will learn how to restrict access to controller methods, use filters for authentication, and more. This article is excerpted from chapter four of the Rails Cookbook, written by Rob Orsini (O'Reilly, 2007; ISBN: 0596527314). Copyright © 2007 O'Reilly Media, Inc. All rights reserved. Used with permission from the publisher. Available from booksellers or direct from O'Reilly Media.

Author Info:
By: O'Reilly Media
Rating: 5 stars5 stars5 stars5 stars5 stars / 4
February 14, 2008
TABLE OF CONTENTS:
  1. · Controlling Information Access with the Rails Action Controller
  2. · 4.13 Sending Files or Data Streams to the Browser
  3. · 4.14 Storing Session Information in a Database
  4. · 4.15 Tracking Information with Sessions
  5. · 4.16 Using Filters for Authentication

print this article
SEARCH DEVARTICLES

TOOLS YOU CAN USE

advertisement
Controlling Information Access with the Rails Action Controller - 4.15 Tracking Information with Sessions
(Page 4 of 5 )

Problem

You want to maintain state across several web pages of an application without using a database.

Solution

Use Rails’s built-in sessions to maintain state across multiple pages of a web application, such as the state of an online quiz.

Create an online quiz that consists of a sequence of questions, one per page. As a user proceeds through the quiz, her score is added to the total. The last screen of the quiz displays the results as the number correct out of the total number of questions.

Create a QuizController that includes a data structure to store the questions, optional answers, and correct answers for each question. The controller contains methods for displaying each question, checking answers, displaying the results, and starting over.

app/controllers/quiz_controller.rb:

  class QuizController
< ApplicationController

    @@quiz = [
      { :question => "What's the square root
of 9?",
        :options => ['2','3','4'],
        :answer => "3" },
      { :question => "What's the square root
of 4?",
        :options => ['16','2','8'],
        :answer => '16' },
      { :question => "How many feet in
a mile?",
        :options => ['90','130','5,280',
'23,890'],
        :answer => '5,280' },
      { :question => "What's the total area
of irrigated land in Nepal?",
        :options => ['742 sq km','11,350
sq km','5,000 sq km',
                      'none of the above'],
        :answer => '11,350 sq km' },
  ]

  def index
    if session[:count].nil?
      session[:count] = 0
    end
    @step = @@quiz[session[:count]]
  end

  def check
    session[:correct] ||= 0
    if params[:answer] == @@quiz[session[:count]][:answer]
     
session[:correct] += 1
    end
    session[:count] += 1
      @step = @@quiz[session[:count]]
      if @step.nil?
        redirect_to :action => "results"
      else
        redirect_to :action => "index"
      end
    end

    def results
      @correct = session[:correct]
      @possible = @@quiz.length
    end

    def start_over
      reset_session
      redirect_to :action => "index" 
    end
  end

Create a template to display each question along with its optional answers: app/views/quiz/index.rhtml:

  <h1>Quiz</h1>

  <p><%= @step[:question] %></p>

  <% form_tag :action => "check" do %>
    <% for answer in @step[:options] %>
      <%= radio_button_tag("answer", answer, checked = false) %>
        <%= answer %>;
    <% end %>
    <%= submit_tag "Answer" %>
  <% end %> 

At the end of the quiz, the following view displays the total score along with a link prompting to try again:

app/views/quiz/results.rhtml:

  <h1>Quiz</h1>

  <p><strong>Results:</strong>
    You got <%= @correct %> out of <%= @possible %>!</p> 

  <%= link_to "Try again?", :action => "start_over" %>

Discussion

The Web is stateless, which means that each request from a browser carries all the information that the server needs to make the request. The server never says, “Oh, yes, I remember that your current score is 4 out of 5.” Being stateless makes it much easier to write web servers but harder to write complex applications, which often need to remember what went before: they need to remember which questions you’ve answered, what items you’ve put in your shopping cart, and so on.

This problem is solved by the use of sessions. A session stores a unique key as a cookie in the user’s browser. The browser presents the session key to the server, which can use the key to look up any state that it has stored as part of the session. The Web interaction is stateless: the HTTP request includes all the information needed to complete the request. But that information contains information the server can use to look up information about previous requests.

In the case of the quiz, the controller checks the answers to each question and maintains a running total, storing it in the session hash with the :correct key. Another key in the session hash is used to keep track of the current question. This number is used to access questions in the @@quiz class variable, which stores each question, its possible answers, and the correct answer in an array. Each question element consists of a hash containing all the information needed to display that question in the view.

The index view displays a form for each question and submits the user’s input to the check action of the controller. Using session[:count], the check action verifies the answer and increments session[:correct] if it’s correct. Either way, the question count is incremented, and the next question is rendered.

When the question count fails to retrieve an element—or question—from the @@quiz array, the quiz is over, and the results view is rendered. The total correct is pulled from the session hash and displayed with the total number of questions, which is determined from the length of the quiz array.

A quiz such as this lends itself reasonably well to the convenience of session storage. Be aware that sessions are considered somewhat volatile and potentially insecure, and are usually not used to store critical or sensitive information. For that type of data, a traditional database approach makes more sense.

Figure 4-3 shows the four steps of the session-driven online quiz.

Rails session support is on by default. As the solution demonstrates, you can access the session hash as if it’s just another instance variable. If your application doesn’t need session support, you can turn it off for a controller by using the :disabled option of Action Controller’s session method in the controller’s definition. The call to disable session support for a controller may also include or exclude specific actions within a controller by passing a list of actions to session’s :only or :except options. The following disables session support for the display action of the NewsController:

  class NewsController
< ActionController::Base
    session :off, :only => "display"
  end

To turn session support off for your entire application, pass :off to the session method within your ApplicationController definition:

  class ApplicationController
< ActionController::Base
   
session :off
  end


Figure 4-3.  An online quiz saving state with sessions

See Also


blog comments powered by Disqus
RUBY-ON-RAILS ARTICLES

- Adding Style with Action Pack
- Handling HTML in Templates with Action Pack
- Filters, Controllers and Helpers in Action P...
- Action Pack and Controller Filters
- Action Pack Categories and Events
- Logging Out, Events and Templates with Actio...
- Action Pack Sessions and Architecture
- More on Action Pack Partial Templates
- Action Pack Partial Templates
- Displaying Error Messages with the Action Pa...
- Action Pack Request Parameters
- Creating an Action Pack Registration Form
- Ruby on Rails Templates and Layouts
- Action Pack Controller Creation
- Writing an Action Pack Controller

Dev Articles Forums 
 RSS  Articles
 RSS  Forums
 RSS  All Feeds
Weekly Newsletter
 
Developer Updates  
Free Website Content 
Contact Us 
Site Map 
Privacy Policy 
Support 



© 2003-2012 by Developer Shed. All rights reserved. DS Cluster 2 - Follow our Sitemap
Popular Web Development Topics
All Web Development Tutorials