<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="/stylesheets/rss.css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>The Vose Way: Category Design</title>
    <link>http://www.chuckvose.com/articles/category/design</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>A Blog about Butter, Cheese, and Ruby on Rails</description>
    <item>
      <title>Using Rails to Create a Static Site</title>
      <description>&lt;h2&gt;Overview&lt;/h2&gt;


	&lt;p&gt;A customer of ours has a splendidly restrictive environment which I have the pleasure to work within. Not only is there no Rails, there&amp;#8217;s no &lt;span class="caps"&gt;PHP&lt;/span&gt; and presumably no database to hook into even if there were dynamic languages. This is probably complete crap but it led to an interesting problem solving situation regardless.&lt;/p&gt;


	&lt;p&gt;What do you do with a client that wants hundreds of pages to be redesigned when you don&amp;#8217;t have access to handy timesaving tools like Rails or &lt;span class="caps"&gt;PHP&lt;/span&gt;?&lt;/p&gt;


	&lt;p&gt;Long before I started research I told my boss to continue with the site anyways; I thought that caching would work exactly the way I needed. This turned out to be completely wrong but the site was well underway so I had to figure something out.&lt;/p&gt;


	&lt;p&gt;After trolling the net for a long time I stumbled on a website that took &lt;span class="caps"&gt;ASP&lt;/span&gt; pages and made static pages out of them by spidering; basically wget tweaked a little bit and resold for far too much money.&lt;/p&gt;


	&lt;p&gt;So I endeavored to do exactly the same for Rails.&lt;/p&gt;


	&lt;h2&gt;Routing&lt;/h2&gt;


	&lt;p&gt;In order to make this work I knew that I needed to do be able to represent pages by their name; something like activities.html would pull up the page with the title &amp;#8216;Activities&amp;#8217;. Once I had the idea it was a short jump to the following routing rules:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;map.connect '', :controller =&amp;gt; 'page', :action =&amp;gt; 'splash_page'
map.connect ':id', :controller =&amp;gt; 'page', :action =&amp;gt; 'index'
map.connect ':controller/:action/:id'&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;The first allows the blank page to be a custom welcome page as is standard for us. The third is the standard route just in case, but the second is the monkey-maker.&lt;/p&gt;


	&lt;p&gt;I realize now that I could have just made &lt;page.id&gt;.html but I&amp;#8217;ve justified it to myself by saying that the titles make for better presentation.&lt;/p&gt;


	&lt;h2&gt;The Code&lt;/h2&gt;


	&lt;p&gt;The code below is the default action for the controller and essentially fills the spot of the routing code with a couple of tweaks.&lt;/p&gt;


	&lt;p&gt;The index bases decisions on whether there&amp;#8217;s just a number, whether there&amp;#8217;s a .html, or just straight text.&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;def index
  # If there's a number in the id assumed that it's the id of a page.
  if params[:id] =~ /^\d+$/
    @page = Page.find(params[:id])

  # If there's a .html in the id assume we want the page with that title.
  elsif params[:id] =~ /^.*\.html$/
    # This allows users to use any case for the link name.
    # Otherwise exporting to windows/mac might break from
    # multiple pages being named the same. For instance
    # Index.html != index.html in Linux but does in Windows/Mac.
    # Therefore sending both versions will break a
    # lot of archiving utilities in Win/Mac.
    if params[:id] =~ /[A-Z]/
      redirect_to :action =&amp;gt; :index, :id =&amp;gt; params[:id].downcase
    end
    # Otherwise strip the .html and the _ then query the database.
    @page = Page.find(:first,
                      :conditions =&amp;gt; ['title = ?', html_to_title(params[:id])])

  # Finally if theres simply a name we should redirect to 
  # the .html version like we did above.
  elsif params[:id]
    redirect_to(:action =&amp;gt; :index, 
                :id =&amp;gt; title_to_html(params[:id])
  end

  # If the page somehow makes it through that battery 
  # and the routing rules above just redirect to the 
  # homepage keeping the flash intact.
  if @page.nil?
    flash[:notice] = flash[:notice]
    redirect_to :action =&amp;gt; :splash_page
  end
end&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Finally there are the helper scripts used above:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;def title_to_html(title)
  title.downcase.tr('\ \\\/', '_') + '.html'
end

def html_to_title(title)
  title.gsub(/\.html/,'').humanize
end&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;h2&gt;Wget&lt;/h2&gt;


	&lt;p&gt;Now that we have pages that are entirely named correctly we can simply use wget to create a perfect copy on her server.&lt;/p&gt;


	&lt;p&gt;For easy reference I used the following:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;wget -m -nH www.example.com&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;h2&gt;Conclusion&lt;/h2&gt;


	&lt;p&gt;After hours of tweaking I&amp;#8217;ve arrived at a very stable and comfortable arrangement. The client knows that pages are simply the name of the page with underscores for spaces and for the most part things are working nicely.&lt;/p&gt;


	&lt;p&gt;Changing page titles is still a pain and probably always will be. We dealt with this by making a links area above the text which adds some order while solving the interpage problem. I think there are currently only two links in the actual pages that point to a page on the server.&lt;/p&gt;


	&lt;p&gt;When using wget it&amp;#8217;s especially important to make sure that all the links are the same style. For instance having a / in front of some links but not in front of others can lead to weirdness when you&amp;#8217;re in a sub-directory and having mixed case will break windows servers (though I&amp;#8217;ve attempted to remedy this).&lt;/p&gt;


	&lt;p&gt;Another caveat is that wget doesn&amp;#8217;t follow javascript links, pop-ups, or roll-overs. All pages that can only be accessed through a form or a js action need to be manually copied with the rest of the files.&lt;/p&gt;


	&lt;p&gt;If nothing this project makes for an interesting comparison in benchmarking. If you were benchmarking the caching ability of a Rails app it would be lovely to see the speed of the straight html as well.&lt;/p&gt;</description>
      <pubDate>Thu, 20 Apr 2006 14:04:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:c88e1885-136a-48e1-93a7-33be6c7bd560</guid>
      <author>vosechu@create-on.com (Chuck Vose)</author>
      <link>http://www.chuckvose.com/articles/2006/04/20/monkey</link>
      <category>Design</category>
      <category>Rails</category>
      <trackback:ping>http://www.chuckvose.com/articles/trackback/1</trackback:ping>
    </item>
  </channel>
</rss>
