Ruby is a programming language that originated in Japan and has gained many fans due to its simplicity. Ruby is one of the few languages that could be described as “fun”. Ruby comes pre-installed on all Mac OSX machines. You can open an interactive ruby shell by executing irb and typing ruby statements after the >> Wherever you see the >> in examples, you can run the command in the irb shell. Note that the return value is always printed last.
$ irb
>> puts "hello"
hello
=> nil
>> quit
Ruby has a few unique characteristics:
This is perfectly valid ruby:
i = 10
puts i
This is the same thing:
i = 10;
puts(i);
Blocks are a useful way to wrap up a set of functionality related to one object, or, to just iterate over a loop.
This is what a block looks like.
>> 5.times do |i|
>> puts i
>> end
0
1
2
3
4
Blocks can also be called with curly braces, {} for brevity. Generally “do..end” is used when there is more than one line in the block.
>> 5.times { |i| puts i }
0
1
2
3
4
Note that curly braces are also used for hashes.
{ 'user' => 'joe', 'id' => 5 }
We can also write some advanced functionality where the block looks like
User.with_options({ 'name' => 'joe' }) do
User.find_by_id(params[:id])
end
Everything in ruby is an object. Every object belongs to a Class and has methods which can be called on it.
>> 1.class
=> Fixnum
>> "hello".class
=> String
>> "hello".reverse
=> "olleh"
>> 1.reverse
NoMethodError: undefined method `reverse' for 1:Fixnum
from (irb):10
You can create your own classes. Here we create a user class and hard-code the name method.
>> class User
>> def name
>> "joe"
>> end
>> end
=> nil
Now you can instantiate a user (note: lowercase) from the User class.
>> user = User.new
=> #<User:0x35a1b0>
>> user.name
=> "joe"
This is a very barebones introduction to Ruby, but there are plenty of resources out there to get more information.
Ruby on Rails is an open source web framework written in Ruby. David Heinemeier Hansson extracted the Rails framework from the code written for his company’s project management tool Basecamp (http://www.basecamphq.com/) in July 2004. Since its release, Rails has seen a meteroric rise in popularity, and is now one of the most popular web frameworks.
At its most fundamental level, Rails is a collection of code libraries that helps write web applications. Much of the common functionality in building an application is included.
Rails adheres to the Model-View-Controller architecture pattern to give each and every Rails application the same structure. This pattern helps cleanly separate all the concerns of the web application.
The following figure illustrates the relationship.

As a designer, it’s unlikely you’ll have much to do with the model or most of the application’s controller logic. These components lay out the behavior of the web application and are primarily the domain of web developers. The view is where most of your attention will be required: laying out pages, structuring layouts, and generally making the application look pretty.
So now we’re going to take a look at a Rails application and where the views live in the application structure. To generate a Rails application, you run the rails script followed by your application’s name. For example:
rails design_study
You should see a message about Rails generating a lot of files and creating folders, and when it’s done you should have a directory design_study in the directory where you ran the command. If you cd into it, you’ll see a number of folders. Each of these folders houses specific elements of a Rails application:
vendor – This directory is where all third party code will live.tmp – The tmp directory holds all your temporary files like browser session data and temporary files for uploading from a client.test – This is where the automated tests for the application live (they may also have a spec folder where behavior-driven tests from RSpec will go)script – This directory has a lot of utility scripts, some of which we’ll discuss in this section.log – This obviously named directory holds all of your application’s log files.lib – The lib is where “extra” code lives: it’s quite a part of the application but it’s still used in or with the Rails application.doc – All documentation (usually generated from RDoc) goes here.db – This directory contains a few database related files.config – The configuration for your Rails application goes in here.Rakefile – Rake is a system for automating tasks with Ruby. Rails uses Rake for a number of tasks, and you can use this file to add your own tasks.public – This is the “public facing” folder of a Rails application. Assets like JavaScript, images, and static HTML files go in here.app – This is where all of the application code lives, including the view files that you’ll be editing. Inside you’ll find models, views, and controllers directories where each respective part lives.If you start your Rails application with script/server, then you should be able to navigate to “http://localhost:3000” in your browser and see a welcome page from Rails.

What you see there is the index.html in your public/ directory (remember, public/ is the “public facing” folder, so you could also go to “http://localhost:3000/images/rails.png” and see the logo). If you wanted to, you could ditch more HTML files in public and look at them, but that’s not as fun as actually working with Rails, so let’s generate some working code.
To get an actual Rails application working, we’ll need a controller to handle the requests. Rails handles the generation of most code for you, so you can use script/generate to create a new controller for you. The command format is script/generate <controller name> <list of default actions to generate> like so:
script/generate controller page index about
This will generate a number of files for us: the controller code files, testing code files, and view files for the default actions we told it to generate for us. If you look in app/controllers, you should see a file named page_controller.rb. Inside you’ll see some methods defined on the controller class that match what we told script/generate to generate for us:
class PageController < ApplicationController
def index
end
def about
end
end
Now that a controller is in place, we can navigate to “http://localhost:3000/pages/” and “http://localhost:3000/pages/about” and see simple placeholder pages. The source of views for a controller lives in the app/views/<controller name> directory; so in this case, you’ll find the placeholders in app/views/page. If you navigate there, you should see index.html.erb and about.html.erb, each with some placeholder HTML (which you can change at your leisure for fun and profit).
<action>.<format>.<processor>. Depending on the format requested and processor used, you’ll see different file extensions. So, if we were sending back an RSS feed, we’d likely use the XML Builder and our file would look like index.rss.builder. Or your team might use a library called Haml for HTML generation, in which case you’d see index.html.haml.Now that we have some code to work with, let’s take a more in-depth look at the connection between controller and view and a look at where the view fits into the Rails ecosystem.
Views, at their core, simply render a response to a request for an action, so when a user requests the index action on the page controller, asking for HTML, then the view app/views/pages/index.html.erb is rendered. But there is a strong connection between the controller and view. When the request is dispatched to the controller, the controller executes the method and then renders the view in the context of the controller object. The following figure illustrates this relationship a little better.
Since views are rendered in the context of controller objects, they have access to all the methods and instance variables inside the controller. For example, edit your app/controllers/page_controller.rb to look like the following:
class PageController < ApplicationController
def index
@title = "This is the main page."
@introduction = "This will be where we list all of our pages..."
end
def about
end
end
Adding this bit of code creates two instance variables: @title and @introduction. As mentioned earlier, we can access these variables from views, so let’s add them to ours. Blow away the contents of the app/views/page/index.html.erb and insert the following:
<html>
<head>
<title>My Page: <%= @title %></title>
</head>
<body>
<h1><%= @title %></h1>
<p><%= @introduction %></p>
<ul>
<li><a href="/pages/about">About</a></li>
</ul>
</body>
</html>
When you navigate to “http://localhost:3000/pages/”, you should see our title and introduction properly rendered.
So far the URLs to the controller actions have been really obvious: “pages/about” maps to PagesController and the about action. But Rails offers a facility for creating pretty URLs using routing. So we could point “http://localhost:3000/my-great-page” to PagesController’s super_fun_time action. Routing is a great tool because it gives you the flexibility to create search engine- and user-friendly URLs without messing with the structure of your application very much, but it can be a little bit of a hassle to figure out where the routes point if you aren’t on the inside of the application’s development
Fortunately, reading the routes file isn’t hard at all and you should be able to pick it up quite easily. You can find it in your Rails application in config/routes.rb. Below is a pretty normal routes file just for illustration.
Routes.draw do |map|
map.connect 'my_about_page', :controller => 'page', :action => 'about'
map.projects 'projects', :controller => 'page', :action => 'projects'
map.connect 'projects/:name', :controller => 'projects', :action => 'show'
map.connect 'projects/:name/:action', :controller => 'projects'
map.with_options :controller => 'projects' do |projects|
projects.connect 'open_source', :action => 'oss'
projects.connect 'work', :action => 'work'
end
map.resources :jobs
map.root :controller => 'pages', :action => 'index'
map.connect ':controller/:id/:action'
end
You can probably already tell what many of these do, but let’s look at these separately…
map.connect connects a route to a controller. The parameters provided tell the router what controller and action to map the string to. In this case, “http://localhost:3000/my_about_page” will map to PageController’s about action.map.projects is a named route. That means that instead of having to specify the controller and action when we want to link to this route using the helper (see below), then we can use projects_path. These routes are the same as normal routes, only slightly more convenient.map.connect calls show using route parameters. In the route string of the first route, :name is a parameter that will be available to the controller in the params collection. So, “http://localhost:3000/projects/rails” will route to ProjectsController’s show action and give it rails in its params. The next route merely illustrates that you can even have the action being called on the controller be a parameter. For example, “http://localhost:3000/projects/rails/edit” will route to ProjectsController’s edit action with rails as a parameter in params.map.with_options is a way to make your routes file a little neater. In this case, any route inside of its block will have projects as its :controller parameter. You can specify any number of parameters with with_options.map.resources sets up routing for RESTful resources. It creates a number of routes used for showing, editing, creating, and so on operations on resources.map.root maps a route to the root URL (i.e., “/” or “http://localhost:3000/”).Along with variables and methods inside the controller classes, Rails also exposes a number of helper methods to views. There are a large number of these, most of which you can read about in Agile Web Development with Rails, The Rails Way, or the Rails API documentation. But here are a few very common methods that you will use…
Linking to Rails actions could be a hassle if you had to give the URL as a constant every time:
<a href="/pages/13/show/preview">Preview</a>
This could be especially annoying if your application uses routing that changes since you’d have to go back and change all your links to match the new routing. Fortunately Rails has a nice helper, link_to, that will generate links for you using the routing system to generate proper URLs. For example, to generate a link to PageController’s index action, you should do something like this in a view:
<%= link_to 'Go to index', :controller => 'page', :action => 'index' %>
That ERb will generate a link on your page with the text “Go to index” that points to the PageController’s index action, regardless of whether it’s routed to pages/ or weird/routing/scheme/25. You can also use the link_to helper to link to the named routes discussed above. For example, if you had a resource users, you could use link_to like so:
<%= link_to 'View all users', users_path %>
That ERb will generate a link that points to users/ with the text “View all users”.
To add any extra HTML attributes you might need like class or id, you need to change the structure of the link_to call a little bit. For example, if you wanted to make a login link that had the class menu_link and the id login, you could do something like the following:
<%= link_to 'Login', { :controller => 'sessions', :action => 'new' }, :id => 'login', :class => 'menu_link' %>
# If you had a named route...
<%= link_to 'Login', login_path, :id => 'login', :class => 'menu_link' %>
Both of these calls (with the proper controllers and routing in place) will generate a link to “sessions/new” with the proper CSS information. You can read more about the options available on this helper and others in the Rails API documentation.
Rails not only provides a helper for linking to other Rails actions, but also to assets such as images and JavaScript files.
To link to an image, you can use the image_tag helper. Note that the file must be placed in the public/images directory for the helper to be able to find it.
<%= image_tag 'rails.png' %>
Much like link_to, you can add extra HTML options by appending them to the end of the call.
<%= image_tag 'profiles/theodore.png', :class => 'profile_picture' %>
To include a JavaScript file, you can use javascript_include_tag. This helper creates a <link> tag for JavaScript files in the public/javascripts directory.
<%= javascript_include_tag 'myfile' %>
Rails comes prepackaged with Prototype and Scriptaculous, so to include those, you simply need to do the following:
<%= javascript_include_tag :prototype %>
<%= javascript_include_tag :scriptaculous %>
There are also special values you can provide: :default will include all of the default, prepackaged JavaScripts and :all will include everything in the public/javascripts directory.
To include a CSS file that lives in public/stylesheets, you can use the stylesheet_link_tag helper.
<%= stylesheet_link_tag 'site_blue' %>
This call will generate a <link> tag that will include public/stylesheets/site_blue.css.
The form helpers in Rails offer a convenient way to generate forms using the Rails routing system to generate the URLs, but they also offer convenience methods for generating fields for the forms and mapping those to database objects.
The simplest of these methods is form_tag, which generates a simple <form> tag. The form_tag takes a block containing form elements to be generated. For example:
<% form_tag posts_path do %>
<%= text_field_tag :title %><br />
<%= text_area_tag :body %><br />
<%= submit_tag %>
<% end %>
The methods text_field_tag and text_area_tag generate fields in the form named for the parameter given to them. Here is a full list of the available form element helpers:
check_box_tagfield_set_tagfile_field_tagtext_area_tagtext_field_taghidden_field_tagimage_submit_tagpassword_field_tagradio_button_tagselect_tagsubmit_tagMany of these works a little differently that text_*_tag, so you’ll want to refer to the API documentation when you want to use them.
Another way to generate form is the form_for, which will generate a form based on an ActiveRecord database object. This helper has two advantages. First, it will only allow you to add fields for values that attributes of the object, making generating forms for database objects very simple. Second, it will refill the form with the user’s input from the last request if there are errors with the form’s submission (Trivial? Maybe, but definitely a nice feature and a time saver). Using form_for requires an object (in our example, we’ll call it @blog_post) to base the form off of:
<% form_for @blog_post do |f| %>
<%= f.text_field :title %><br />
<%= f.text_area :body %><br />
<%= f.select_field :author, @authors %><br />
<% end %>
Notice the API differences: the helper names lack _tag and they are now called on an object yielded to the form_for’s block. Here is a list of the form_for helpers.
check_boxfields_forfile_fieldform_forhidden_fieldlabelpassword_fieldradio_buttontext_areatext_fieldBoth these helpers and the _tag helpers will take HTML options as parameters, much like other Rails helpers. You’ll want to look at the API documentation for information on that because they often have to be treated differently because of the parameters the different helpers require.
Rails offers a number of helpers for AJAX and other JavaScript-related functionality, but for the most part they aren’t useful if you already know JavaScript really well. The one helper that is quite useful is link_to_remote. It acts like link_to, except that it makes an AJAX call rather than a normal synchronous HTTP request.
For example, if we were to link to an action that will delete a blog post, we might do something like the following:
<%= link_to_remote "Delete this post", { :update => 'posts',
:url => { :controller => 'posts', :action => 'destroy', :id => post.id } } %>
The :url parameter obviously gives it the URL to make the request to (using the Rails routing system). The :update parameter tells Prototype the id of the element it should update with the results of the request when it’s completed. You can add HTML options to the link just like you can with link_to by adding them as a Hash in the :html parameter.
If you want to update different parts of the page depending upon the success or failure of the request, then you can add :success and :failure keys to the :update parameter.
<%= link_to_remote "Delete this post", { :update => { :success => "posts", :failure => "error" },
:url => { :controller => 'posts', :action => 'destroy', :id => post.id } } %>
You can learn more about callbacks like :success and :failure in the API documentation for link_to_remote.
remote_form_for and form_remote_tag. They create <form> tags that submit via AJAX.Rails provides a good number of ways for a designer to abstract her views into easy, reusable pieces. We’ll take a look at two of those now: layouts and partials.
A Rails layout lets you provide a common layout for a number of actions. This makes it simple to create a consistent design across your application without having to include a header and footer each time or something similar. Layouts live in the app/views/layouts directory, and have a general structure like the following:
[Before action/header content]
<%= yield %>
[After action/footer content]
The yield statement will yield control of the template’s rendering to the action’s template, then regain it afterwards to complete the layout.

You can specify layouts for a number of scopes: your whole application, each controller, and even specific actions.
To specify an application-wide layout (i.e., a layout that will be applied to every action, in every controller unless told otherwise), you need to create or edit app/views/layouts/application.html.erb.
To specify a layout for a specific controller, simply create a <controller name>.html.erb file (e.g., page.html.erb) in the app/views/layouts/ directory. If you want to specify a layout named different than the controller, use the layout method inside the controller class definition. For example, if we wanted to assign the simple layout to the PageController class from earlier, you’d do something like the following:
class PageController < ApplicationController
layout 'simple'
def index
@title = "This is the main page."
@introduction = "This will be where we list all of our pages..."
end
def about
end
end
All actions dispatched to the PageController class will now be rendered in the app/views/layouts/page.html.erb layout. If you want a controller to render without a layout, then call layout with nil as the layout name.
You can restrict which actions get a layout using the :only and :except parameters like so:
layout 'simple', :only => [:index, :show]
The value provided is an array of action names that will receive the layout. When using this parameter, other actions will have no layout or, in the case of :except all other actions will have a layout. You can only call layout once to set the layout, so you can’t use these parameters to set different layouts for different actions, but you can use a trick to get the same effect.
Specifying different layouts in the same controller gets a little trickier. To do that, you’ll need to create a method that returns the name of a layout file to use, then provide the name of that method to layout. For example, if we wanted index to use the controller layout and all other actions to use the simple layout in our PageController, then you would do the following:
class PageController < ApplicationController
layout :choose_layout
def choose_layout
if action_name == 'index'
"page"
else
"simple"
end
end
end
Providing a Symbol to layout like that tells it to call a method rather than interpret it as a string.
Layouts are a great way to share wider design across actions and controllers, but they are not a good mechanism for sharing small pieces of HTML like login forms or blog posts. This sort of sharing is reserved for partials, small pieces of ERb that can be included in any template.

Partials are created by creating an ERb template that have a file name that starts with an underscore, like _form.html.erb or _menu.html.erb. There is no magic in their contents: they are simply pieces of ERb templates. To render a partial in a template, you need to use the render method like so:
<%= render :partial => 'partial_name' %>
The render method will render the partial template and then pass the results back to the parent template to be rendered in place.
The only “gotcha” with partials is that they don’t automatically inherit values from their parent template, but you can still pass them in easily with the :locals parameter. The :locals parameter takes a Hash of values and will create local variables based on the key names. For example, if you wanted to render a “You are a logged in as (x)” message, you could do something like the following:
<%= render :partial => 'logged_in_bar', :locals => {'user' => current_user} %>
And in the partial…
You are logged in as <%= user %>
You can also render partials from another controller’s (or shared) directory like this:
<%= render :partial => 'path/partial_name' %>
The path given is relative to app/views (so in this case it will render app/view/path/_partial_name.html.erb).
Partials can have layouts, too. To use a layout with a partial, create another partial and call render with the :layout parameter.
<%= render :partial => 'moderator', :layout => 'user' %>
This call will render the moderator partial, using the user partial as a layout. The _user.html.erb should look something like the following:
<div class="user">
<b>User</b>
<%= yield %>
</div>
As you can see, just like “real” layouts, you use yield to give control over to the child template.
The most obvious solution to rendering a partial for each member of a collection is to loop over the collection and render the partial for each item that is iterated over, but that’s not the best solution in Rails. The render method can take a :collection parameter that will do all this work for you:
<%= render :partial => 'post', :collection => @posts %>
This will render a partial post for each element of @posts. In the partial, a local named post will be created that points to the item being yielded to the partial.
– This might be a bit above the intended reader’s level…not sure…
Simple markup interpolation abstraction
Fancier abstractions
– I thought maybe she could use this guide to work on an app, and keep a journal/document her progress; then we could tweak the guide and write this section based on that