<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Blog.ubrious &#187; themes</title>
	<atom:link href="http://blog.ubrio.us/tag/themes/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.ubrio.us</link>
	<description>An Ordinary Web Developer's Blog</description>
	<lastBuildDate>Thu, 19 Jan 2012 00:44:59 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Rails theme support with Metal</title>
		<link>http://blog.ubrio.us/ruby/rails-theme-support-with-metal/</link>
		<comments>http://blog.ubrio.us/ruby/rails-theme-support-with-metal/#comments</comments>
		<pubDate>Wed, 11 Mar 2009 22:30:12 +0000</pubDate>
		<dc:creator>Rob Hurring</dc:creator>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[metal]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[rails 2.3]]></category>
		<category><![CDATA[themes]]></category>

		<guid isPermaLink="false">http://blog.ubrio.us/?p=167</guid>
		<description><![CDATA[Metal is neat. Themes are neat. Together they are nifty. So, in the spirit of the upcoming St. Patrick&#8217;s day holiday I decided to play around with metal to add theme support to my rails app. I like how Wordpress supported themes by having meta data tucked into the stylesheet itself, and I also like [...]]]></description>
			<content:encoded><![CDATA[<p>Metal is neat. Themes are neat. Together they are nifty. So, in the spirit of the upcoming St. Patrick&#8217;s day holiday I decided to play around with metal to add theme support to my rails app. I like how Wordpress supported themes by having meta data tucked into the stylesheet itself, and I also like query string (odd, I know) &#8212; so I figured I&#8217;d melt them together&#8230; in the spirit of the holiday and all.</p>
<p><a name='themes'></a></p>
<h3>The Theme Files</h3>
<p>First things first. We need to create a themes folder. I chose <tt>RAILS_ROOT/public/stylesheets/themes</tt> but anywhere public would work. Inside there I threw the following stylesheet:</p>
<p>I made the theme support a minimum of 3 meta fields:</p>
<ol>
<li><strong>theme</strong> &#8212; The name of the theme</li>
<li><strong>begin</strong> &#8212; What date to start using the theme</li>
<li><strong>end</strong> &#8212; What date to stop using the theme</li>
<li><strong>*enabled</strong> &#8212; Optional: If you want to enable this theme</li>
</ol>
<p>You can hack on this and include as many as you want &#8212; they follow the same basic format as URLs:</p>
<p><code><span>theme.css</span>theme=My Themes Name&#038;begin=March 17&#038;end=March 18</code></p>
<pre class="brush: css;">
/*
RAILS_ROOT/public/stylesheets/themes/st_patricks_day.css
{{
	theme=st patricks day
	&amp;begin=March 17
	&amp;end=March 18
	&amp;enabled=1
}}
*/

#header{
	background:#C2DDCA url(theme_images/shamrock.png) no-repeat 25px 20px;
	padding-left:50px;
	}
</pre>
<p><a name='metal'></a></p>
<h3>The Metal</h3>
<p>And, now into the neat part. Generate a rails metal file to handle theme switching on the fly, according to the current date.</p>
<p><code><span>$></span>./script/generate metal theme</code></p>
<p>Which should give you a nice <tt>app/metal/theme.rb</tt> file which you can play with.</p>
<p>I hacked together this code &#8212; and I&#8217;m not sure how stable it is, but should probably used in production with caution. It uses <tt>Rails.cache</tt> so make sure in your <tt>environment.rb</tt> file you have a cache store set.</p>
<pre class="brush: ruby;">
class Theme
  # this is where the theme index is stored
  CacheKey = 'themes'
  # this is what we will look for in the layout
  ThemeEnvKey = 'rails.theme'
  # this is the path to your themes folder
  ThemesPath = File.join(RAILS_ROOT, 'public', 'stylesheets', 'themes')

  def self.call(env)
    # Build our theme index
    themes = Rails.cache.fetch(CacheKey) do
      data = {}
      Dir[File.join(ThemesPath, '*.css')].each do |theme|
        # looks for {{ url_type_string_here }} comment meta data and parses
        # it out into a hash for the theme's file name
        #
        # within your theme file, you would have:
        #   {{theme=my name&amp;begin=DATE&amp;end=DATE}}
        # becomes
        #   {'theme.css' =&gt; {:theme =&gt; 'my mane', :begin =&gt; 'START_DATE', :end =&gt; 'FINISH_DATE'}}
        #
        # DATE is parsed so it can be any type of
        # date-ish string see ActiveSupport::TimeZone#parse
        begin
          data[File.basename(theme)] = \
            $1.split('&amp;').inject({}) do |h, v|
              s = v.split('=').map(&amp;:strip)
              h[s.first.to_sym] = s.last
              h
            end if File.read(theme) =~ /\{\{(.+)\}\}/m
        rescue Exception =&gt; e
          data[theme] = {:error =&gt; e.to_s}
        end
      end
      data
    end

    # Set the appropriate theme
    now = Time.zone.now.beginning_of_day
    themes.each_pair do |file, data|
      next if data.keys.include?(:enabled) and data[:enabled].to_i.zero?
      next unless data.keys.include?(:begin) and data.keys.include?(:end)

      if Time.zone.parse(data[:begin]) &lt;= now and Time.zone.parse(data[:end]) &gt; now
        env[ThemeEnvKey] = file
        break
      end
    end

    # pass
    Rails::Rack::Metal::NotFoundResponse
  end
end
</pre>
<p>What this basically does is:</p>
<ol>
<li>Check within the <tt>ThemesPath</tt> for any .css files</li>
<li>Reads them and parses out the metadata within the stylesheet</li>
<li>Caches that</li>
<li>Checks the date to see if any theme files should be turned on</li>
<li>Sets an <tt>env</tt> key to let the rest of Rails know we want a theme</li>
</ol>
<p><a name='layout'></a></p>
<h3>The Rails Layout</h3>
<p>Well, now Metal has set our <tt>env['rails.theme']</tt> key so we know a theme is in order it is time to put that theme to use.</p>
<div class='tip'>
Some DRYing is in order to make sure the metal and layout share the same <tt>env</tt> keys and paths, but this should get your basic themes goin.
</div>
<pre class="brush: ruby;">
# your applications main layout file (app/views/layouts/application.html.erb?)
# I put this after the normal stylesheet call, so our theme can override what we want instead of the entire stylesheet

&lt;% if theme = request.env['rails.theme'] %&gt;
  &lt;%= stylesheet_link_tag &quot;themes/#{theme}&quot;, :media =&gt; :all %&gt;
&lt;% end %&gt;
</pre>
<p>Once all these steps are combined, and March 17th hits, we should now have a stylish header image that shows the shamrock.png! I can almost hear the users clinging glasses <img src='http://blog.ubrio.us/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<div id='tip'><a href='http://gist.github.com/79871' onclick="pageTracker._trackPageview('/outgoing/gist.github.com/79871?referer=');">View as Gist</a></div>
]]></content:encoded>
			<wfw:commentRss>http://blog.ubrio.us/ruby/rails-theme-support-with-metal/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

