Rails Introduction: Templates and Controllers

Lecture Notes for CS 142
Spring 2012
John Ousterhout

History of Web Frameworks

  • Initially: static HTML files only.
  • CGI:
    • Certain URLs map to executable programs
    • When URL is referenced, program runs
    • Program's output is returned as the Web page
    • Program exits after Web page complete
    • Introduced the notion of stateless servers: each request independent, no state carried over from previous requests.
    • Perl typically used for writing CGI programs
  • First-generation frameworks (PHP, ASP.net, Java servlets):
    • Incorporate language runtime system directly into Web server
    • Templates: mix code and HTML
    • Web-specific library packages:
      • URL handling
      • HTML generation
      • Sessions
      • Interfacing to databases
  • Second-generation frameworks (Ruby on Rails, Django):
    • Object-relational mapping: simplify the use of databases (make database tables and rows appear as classes and objects)
    • Model-view-controller: stylized decomposition of applications.


  • Rails: a Web application framework based on the Ruby language. Often referred to as "Ruby on Rails".
  • Rails applications have an MVC (model-view-controller) structure:
    • Model: manages the application data
      • Each class encapsulates the data in a particular database table.
    • View: generates Web page.
    • Controller: glue between the model and view:
      • Responds to incoming HTTP requests
      • Fetches/modifies data in the models
      • Invokes view(s) to render results
    • The MVC pattern has been around since the late 1970's; originally conceived in the Smalltalk project at Xerox PARC.

Templates (Views)

  • The most common way to generate dynamic HTML; available in virtually all Web development frameworks.
  • Simple Rails example:
    <?xml version="1.0" encoding="utf-8"?>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
        <title>Hello, User</title>
        This page was fetched at <%= Time.now() %>
  • Basic ideas:
    • Write HTML document containing parts of the page that are always the same.
    • Add bits of code that generate the parts that are computed for each page.
    • The template gets expanded by executing code snippets, substituting the results into the document.
  • Two kinds of annotation in Rails templates:
    • <%= ... %>: substitute value of expression
    • <% ... %>: execute Ruby code, but no substitution of result: use concat in code to generate HTML
  • Benefits of templates:
    • Easy to visualize HTML structure
    • Easy to see how dynamic data fits in
  • Can interleave Ruby control structures with HTML:
    <?xml version="1.0" encoding="utf-8"?>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
        <title>Rails Parameters</title>
        The <code>params</code> hash contains the following values:
        <% params.each do |key, value| %>
          <p><%= key %>: <%= value %></p>
        <% end %>
  • Query values available through params.
  • Rails automatically escapes anything substituted with <%=
  • Use html_safe to indicate that a value should not be escaped
  • Useful "helper" functions for Rails templates:
  • link_to: convenient for generating links:
    <%= link_to(@name, {:action => "userInfo", :id => @user_id}) %>
  • Including stylesheets or Javascript (files must be in app/assets/stylesheets or app/assets/javascripts):
    <%= stylesheet_link_tag "styles" %>
    <%= javascript_include_tag "file1", "file2" %>


  • Most code should be in controller, not template; all template does is substitute values into HTML. Controller also interfaces with models, which manage application data.
  • Lifecycle of an HTTP request:
    • Dispatching:
      • Rails receives incoming request
      • Rails invokes a method in a Controller class, based on the URL:
        • Default: URL /rails_intro/hello will be dispatched to method hello in class RailsIntroController. The controller should be defined in the file app/controllers/rails_intro_controller.rb
        • You can define other mappings using Rails routes.
      • The controller method corresponding to a URL is called an action method.
      • Controller can have several action methods; typically a controller manages a related group of URLs.
      • Rails makes URL information available to action methods:
        • params holds query values
        • If the URL had the form /class/method/id, where id is an integer, then that value is available through params[:id]. Commonly used to hold the primary key for a database record to display the page.
    • Controller action method:
      • Collects data needed to generate the page, saves in instance variables of the controller object.
      • Typically does this by calling Model classes.
    • By default, Rails automatically invokes the view once the controller action method returns.
      • For URL /rails_intro/hello, view file is app/views/rails_intro/hello.html.erb
      • Controller can override this by invoking render explicitly.
  • Example: controller to compute primes:
    class RailsIntroController < ApplicationController  
      def showPrimes
        # Query value "count" indicates how many primes to
        # compute (default: 10)
        if (params[:count] != nil) then
            count = params[:count].to_i()
            count = 10
        # Fill in @primes array with prime numbers
        @primes = []
        candidate = 2
        while (@primes.length < count)
          isPrime = true
          # If any of the known primes divides into the candidate
          # evenly, then the candidate isn't prime.
          @primes.each do |prime|
            if ((candidate % prime) == 0) then
              isPrime = false
          if (isPrime) then
              @primes << candidate
          candidate += 1
  • Corresponding view:
    <?xml version="1.0" encoding="utf-8"?>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
        <title><%= @primes.length %> Prime Numbers</title>
        <%= stylesheet_link_tag 'main' %>
        The first <%= @primes.length %> prime numbers are:
        <table class="oddEven" cellspacing="0">
          <tr class="header"><td>Prime Numbers</td></tr>
          <% @primes.each do |prime| %>
            <tr class="<%= cycle('odd', 'even') %>">
              <td><%= prime %></td>
          <% end %>

Directory Structure

  • Rails assumes a particular file structure for applications. Some example directories:
    • app/controllers: Ruby files containing controller classes
    • app/models: model definitions
    • app/views/controller: template files for the controller named controller
    • db/migrate: database migration files
    • public: static files accessible via URLs
    • public/images/iii: image file accessible at the URL /images/iii
    • app/assets/javascripts/myCode.js: Javascript file corresponding to
      <%= javascript_include_tag myCode %>
    • app/assets/stylesheets/myStyles.css: CSS file corresponding to
      <%= stylesheet_link_tag myStyles %>


  • Layout: standard frame used for one or more pages
    • DOCTYPE and other boilerplate
    • Header, footer, sidebar, etc.
  • yield marks where the main template should be inserted.
  • The regular template is expanded before the layout is invoked so it can set variables that personalize the layout for individual pages (e.g., title)
  • Files for layouts:
    • app/views/layouts/xyz.html.erb: default layout for all URLs in XyzController.
    • app/views/layouts/application.html.erb: default layout for all URLs in the application.

Partial-Page Templates

  • Encapsulate the rendering of common elements in a reusable way.
  • Looks like any other template.
  • Invoked with the render method:
    <%= render(:partial => "foo") %>
    Will render the template _foo.html.erb in the same directory as the calling template.
  • Can pass arguments to the rendered template.
    <%= render(:partial => "shared/foo", :locals => {:x => 24, :y =>36}) %>
    • Template is in app/views/shared/_foo.html.erb
    • The template will have local variables x and y.