M@'s Musings

« Back to blog
 

Supporting Themes In Your Rails Application


Update:
There's an updated version of the theme_generator. See the blog post or download it.


I was pretty impressed after looking at the theme support in Typo 2.5. However, I don’t think it’s a system that you should replicate if you want your application to support simple themes.


Before I get too far along let me make it clear that it’s not my intention to cast aspersions on Typo, it’s an excellent tool. In fact, I plan on switching to it from WordPress in the near future.


My issue with Typo’s theme scheme (heh) is that it doesn’t leverage the web-server as it should. Rails is impressive, and it’s caching is quite good. But web-servers like Apache have been around for many years. They are really good at what they do, so let them do it! Rails can’t compete with the server’s ability to deliver static content like CSS and graphics.


Following is how I’ve been implementing themes in Rails applications. In addition to relying on the web-server to provide static files, it also leverages existing Rails infrastructure wherever possible. Bear in mind, I’m not suggesting the following to be an end-all solution. Nor is it a drop-in replacement for Typo’s theme support. Merely think of it as a good starting point.


I’ve been using this approach enough that I’ve created a generator for it.


theme_generator


Usage


After you’ve installed the generator, just call it with the name of the theme you’d like to create.


./script/generate theme blue-bird

It will then add theme_engine.rb to your lib/ folder and create the required file structure.


Note: On Windows, it looks more like:


ruby script\\generate theme blue-bird

File Structure


Let’s start by having a look at the file structure it creates. Here’s an example for a theme named ‘blue-bird’.


app/views/layouts/themes/blue-bird/public/themes/blue-bird/images/javascripts/theme.css

Just from looking at that, you can probably get a good idea where I’m going.


Static Files


All of the static files, CSS, Images, and JavaScripts are under the app/public/themes directory, as they should be. Apache (or lighttpd, or whatever) will happily serve these up for us.


To reference theme-specific images from the CSS it’s as simple as:


[code lang="css"]
BODY {
background: url( images/my-bg.png );
}
[/code]

Be sure to use a relative path to the image. CSS will look for images relative to the CSS file, not the page, remember?


Layouts


You’ll notice under the app/views/layouts folder, I’ve added a theme structure similar to the one under app/public/. As an example, app/views/layouts/themes/default/main.rhtml is the main layout for the ‘default’ theme.


In your controller, you’ll tell Rails that you want a themed layout like this:


[code lang="ruby"]
class MyController << ApplicationController
layout :themed_layout
end
[/code]

Current Theme


The only thing that’s left to your controller is indicating which theme is currently active. It’s as simple as overriding the current_theme method.


[code lang="ruby"]
class MyController << ApplicationController
layout :themed_layout

def current_theme
'blue-bird'
end

end
[/code]

To set the theme for the entire application, you can add that to your ApplicationController instead (in app/controllers/application.rb).


Tag Helpers


To aid in retrieving themed media, helper methods have been added to the ActionView::Helpers::AssetTagHelper module.



  • theme_image_path

  • theme_stylesheet_path

  • theme_javascript_path

  • theme_stylesheet_link_tag

  • [More to come…]


Usage is generally quite simple. In your view, if you want to reference a themed image:


[code lang="xml"]

[/code]

Last, But Not Least


This needs to be included at the bottom of your environments.rb:


[code lang="ruby"]require_dependency 'theme_engine'[/code]

That’s it really—pretty straight forward. If you look at the theme_engine.rb you’ll see it’s a less-is-more type solution.


In the next few days I’ll polish the theme_engine some more, based on the feedback y’all provide, and refactor it into a plugin.

Posted
18 Comments
Oct 25, 2005
Scott Laird said...
It's good to see people taking a look at themes in Rails, but I'm not quite sure what it is that you're unhappy with in Typo. The goal was to get all of the theme-related files in one directory, so they could easily be shipped around and installed by new users. So yes, theme images/js/css live outside of public/. *But*, we're using Rails' page cache for them, which really just means that Rails copies the files into public/ for us and then lets the web server do all of the heavy lifting on its own. Take a look in public/images/themes/. Effectively, we're just using the page cache as an installer.
Oct 25, 2005
Ken said...
I am an active contributor (I have written two modules for the project) to phpWebsite and last week I discovered Ruby and Ruby on Rails. I prefer the "more" object orientation of Ruby and am organizing a RoRWebsite of sorts modeled after phpWebsite.
I prefer the /theme/js..images..etc method of organization as opposed to the /images/theme.. js/theme... etc method because it makes it easier to develop themes for distribution... phpWebsite reads the directories in the theme directory and allow the admin / user to choose the theme. It seems the Typo "methodology" is more problematic to implement. Having said that, I am on the steep incline side of the Ruby learning curve so I could be missing something(s).
There are some features which can be added which include custom meta tags, headers, footers, etc...
I like this implementation of theme-ing.
Regards,
Ken
Oct 25, 2005
Scott Laird said...
There really haven't been many gotchas, but there was one difficult feature--a lot of people requested the ability to have themes override individual views in Typo.
That turned out to be a major pain.
The code is in lib/renderfix.rb in the current Typo trunk. It lets you override views on a per-file basis with views in the theme directory. It does this by reaching deep into the guts of Rails. It's not pretty, but it works. Sooner or later, we'll probably want to add the notion of a view search path to Rails, but I'm not really ready to generalize the patch yet. Maybe once you have your theme generator ready to go it'll make more sense to spend the time on it.
As far as the path name issues in public/, that's something that we're going to have to revisit when we add multi-blog support to Typo. In general, the page cache and support for multiple blogs in a single Typo install don't really mix well, but we should be able to get the theme system to work. We may have to change directories; I haven't really though about it in depth yet. Anyway, it'll be a month or two before we have to worry about that, and we have a new Typo release to get out the door first.
Oct 27, 2005
John said...
Do you have a list of the themes available, w/ sample screenshots? Or is that buried somewhere in the generator?
Oct 27, 2005
Ben Luo said...
What's the lisence of theme_generator?
Oct 27, 2005
M@ said...
Ben: That's a good question.
Typo uses an MIT license. I guess since I make heavy use of that code (with my own additions, obviously) theme_generator will also be under the MIT license.
Which I suppose means I should put that license file in the source, eh?
Oct 28, 2005
jt said...
themes should really just be a .css file and images... no need for a new layout
Oct 28, 2005
Matt said...
jt: Sometimes you want to do different functional things in your theme that requires different code structuring, additional JavaScript, Flash, whatever. You wouldn't want that to be in EVERY theme. Besides, why limit yourself to one layout and force yourself into a ZenGarden type of thing if you don't have to?
M@: Thanks a lot for writing all this up. I need something like this for a project of mine and this should work perfectly.
Oct 28, 2005
hand|paper|lake said...
More Rails Tech
There are a few areas where, at least in the proposal, I down played a some aspects of the project -- mostly in terms of the sorts of compatibilities that may be offered. So, when I see things fly by the Ruby On Rails site, I make some note. I'm sure ...
Nov 01, 2005
Timothy Johnson said...
I am trying to separate the theme into different layouts. Like the home page would get the default layout and articles would get their own layout. Can't really figure it out at this point, but I guess I need to get better at rails anyway
Mar 19, 2006
Full Theme Support in Rails, Revisited at M@ McCray said...
[...] OK, so after a short discussion and some experiments, I’ve realized that the Typo approach to themes has a lot more merit than I initially thought… For general use it still has some trouble areas, but that’s nothing that can’t be fixed. [...]
Aug 13, 2006
bhpetyfbg said...
cdyniixo...
zdybzrznktk ysgtnjoke igukqjrs fsoqybvhu rmvdcrvz...
Aug 13, 2006
silzmmty said...
negzqsshem...
jhgzgrwu jhfqjmoaw ssbqkjpvww rozlispczc rkzgruzqi...
Aug 13, 2006
fplafmr said...
ysiwlgsw...
hnnedvdyo rsjrntqoic hthqnsam owlsabacg pvspnnpm...
Aug 13, 2006
swnwmyhd said...
fjuevfym...
gqlqutzds neqcwvhjqa rnztjockmiy ajwdvpqm mxdmce...
Aug 14, 2006
roxawstksq said...
lomgawwd...
vvaxwyfpw ciupwjjroso fgrmhgfmq fdwtaccabg gsmzepjiak...
Jul 31, 2007
Francis said...
i'm new to ruby on rails. can anyone give me a full documentation on how to use the theme generator? Where to get themes and how to use it? thanks...

Leave a comment...

Theme by Cory Watilo.
More great Posterous themes at themes.posterous.com.