About this entry
You’re currently reading the article “Adding Theme Support to a Ruby on Rails Application.”
- Published:
- November 4th 06:31 PM
- Updated:
- June 11th 06:00 AM
- Sections:
- Ruby on Rails
Adding Theme Support to a Ruby on Rails Application
Suppose that your Ruby on Rails application is a generic one designed to be run customized to the look and feel of each of your client's taste. You can easily make it run in several places, each instance with its own customized stylesheets, javascripts, images, layouts, and views by adding theme support to it. In this article I will show you how.
Liked it? !
Index
- Everybody on the Same Page
- Installing the Necessary Plug-ins
- Creating Themes
- Theme-specific Stylesheets
- Theme-specific Views and Layouts
- Hard-wiring the Selection of the Theme
- Testing the New Theme Support
- Related Articles
- Further Resources
- Coming Soon
Everybody on the Same Page
In order to show how to provide theme support to a Ruby on Rails application, I will illustrate the steps by adding theme support to our basic RESTful social_graph application. Please give it a quick glimpse before continuing with this article, if you haven't done so already.
Installing the Necessary Plug-ins
The plug-in that we are going to use is theme_support. Since it additionally requires the liquid plug-in, we also need to install it. To do so, run the following lines under the social_graph folder:
ruby script/plugin install http://liquid-markup.googlecode.com/svn/trunk ruby script/plugin install http://mattmccray.com/svn/rails/plugins/theme_support
This will create two folders under social_graph\vendor\plugins: theme_support and trunk, which holds the liquid plug-in. Rename "trunk" to liquid in order to make the folder name meaningful!
As of version 1.4.0, theme_support was not fully compatible with rails 1.2.5. Some changes have to be made to the methods draw and create_theme_routes in social_graph\vendor\plugins\theme_support\lib\patches\routeset_ex.rb in order for this to work. First update the draw method to:
def draw clear! create_theme_routes yield Mapper.new(self) named_routes.install end
Now update the create_theme_routes method to:
def create_theme_routes add_named_route 'theme_images', "/themes/:theme/images/*filename", :controller=>'theme', :action=>'images' add_named_route 'theme_stylesheets', "/themes/:theme/stylesheets/*filename", :controller=>'theme', :action=>'stylesheets' add_named_route 'theme_javascript', "/themes/:theme/javascript/*filename", :controller=>'theme', :action=>'javascript' add_route "/themes/*whatever", :controller=>'theme', :action=>'error' end
We are all set! Let's start developing...
Creating Themes
Let's start creating two themes. From the command-line (in the social_graph folder) run the following generators:
ruby script/generate theme default ruby script/generate theme dark
These commands will create the folders default and dark under social_graph/themes. Each will have the subfolders images, javascript, layouts, stylesheets and views, where you the corresponding files for each theme will be. For the images, javascripts, and stylesheets of the right theme to be fetched, you should use the corresponding theme tag helpers that come as an extension to ActionView::Helpers::AssetTagHelper within theme_support to access them: theme_image_path, theme_javascript_path, theme_stylesheet_path, and theme_stylesheet_link_tag. Views and layouts for themes override existing views and layouts.
In order to test these themes out, let's do some changes in order to make them distinguishable.
Theme-specific Stylesheets
For the default layout, let's have the stylesheet be almost the same of the social_graph\public\stylesheets\scaffold.css stylesheet, except for its headers being of a different color. Update social_graph\themes\default\stylesheets\default.css to:
/*
Main StyleSheet for the 'Default' theme
*/
body { background-color: #fff; color: #333; }
h1, h2, h3, h4, h5 {color: #511CFF;}
body, p, ol, ul, td {
font-family: verdana, arial, helvetica, sans-serif;
font-size: 13px;
line-height: 18px;
}
pre {
background-color: #eee;
padding: 10px;
font-size: 11px;
}
a { color: #000; }
a:visited { color: #666; }
a:hover { color: #fff; background-color:#000; }
.fieldWithErrors {
padding: 2px;
background-color: red;
display: table;
}
#errorExplanation {
width: 400px;
border: 2px solid red;
padding: 7px;
padding-bottom: 12px;
margin-bottom: 20px;
background-color: #f0f0f0;
}
#errorExplanation h2 {
text-align: left;
font-weight: bold;
padding: 5px 5px 5px 15px;
font-size: 12px;
margin: -7px;
background-color: #c00;
color: #fff;
}
#errorExplanation p {
color: #333;
margin-bottom: 0;
padding: 5px;
}
#errorExplanation ul li {
font-size: 12px;
list-style: square;
}
div.uploadStatus {
margin: 5px;
}
div.progressBar {
margin: 5px;
}
div.progressBar div.border {
background-color: #fff;
border: 1px solid grey;
width: 100%;
}
div.progressBar div.background {
background-color: #333;
height: 18px;
width: 0%;
}
Make the social_graph\themes\dark\stylesheets\dark.css stylesheet the same, except for the h1, h2, h3, h4, h5 color to be darker:
h1, h2, h3, h4, h5 {color: #404040;}
Theme-specific Views and Layouts
To update the default theme's layout so that it loads the appropriate stylesheet (using the above mentioned theme tag helper) and to display a footer informing the user which theme is being used add the file application.rhtml to the folder social_graph\themes\default\layouts with the following content:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="content-type" content="text/html;charset=UTF-8" />
<title><%= "#{controller.controller_name.capitalize}: #{controller.action_name}" %></title>
<%= theme_stylesheet_link_tag 'default' %>
</head>
<body>
<p style="color: green"><%= flash[:notice] %></p>
<%= yield %>
<h5>Using 'default' theme!</h5>
</body>
</html>
The dark theme layout (social_graph\themes\dark\layouts\application.rhtml) would be almost the same, except that it should load its own stylesheet:
<%= theme_stylesheet_link_tag 'dark' %>
and display its own footer:
<h5>Using 'dark' theme!</h5>
Hard-wiring the Selection of the Theme
Although this is the least convenient approach, it's the easiest to implement and test. In order to force the usage of a the default theme, add a call to the theme method in the ApplicationController. The file social_graph\app\controllers\application.rb will look something like this:
class ApplicationController < ActionController::Base session :disabled => true theme 'default' end
Testing the New Theme Support
Now go ahead and test the application. Try replacing the theme line to:
theme 'dark'
and refreshing the browser. Try deleting the line and refreshing the browser. Cool and easy, isn't it?
Related Articles
Later articles that have built on top this topic are:
- Follow-up on theme_support and integration with rxml templates. This article gives a brief intro to rxml templates and proposes fixes to the theme_support plugin for better integration.
Further Resources
- From Matt McCray, the creator of theme_support see Full Theme Support in Rails, Revisited and his archives on theme_support.
- Liquid Homepage
Coming Soon
- How to add an application settings view to your application, where the admin can specify the theme (instead of hard-wiring it in the code) among other preferences.
- How to make the theme support dependent on the records within a table of the database. For instance, displaying each acquaintance's information with his own theme.
Stay tuned!

1 comment
Jump to comment form | comments rss [?]