Chaining Rails Template (view) Handlers

I have been looking for a way to get rid of all the ERB markup in the file and simply use plain HTML, albeit with my custom set of HTML tags. I don’t want to learn a new markup language just to do something simple but on the same token don’t want <%= … do %> … <% end %> splattered all over the page either. For example, I want to use “<row>…</row>” to invoke/substitute <%= row do %>…<% end %> automatically when the page is processed.

Rails 3 makes it easy to chain preprocessors to assets that will perform manipulations on the file prior to storing it, as the guides talk about here. However, this method limits you to only the assests files – scripts, css, images, for the most part.

I’ve been searching for a way to chain template handlers to action views in the same manner. For example, if you have a file called index.html.erb.something the framework would first process the Something handler, followed by the ERB handler. So far I’ve not been able to find a way to handle it quite in this form, however I have found a way to inject your preprocessing without changing extensions at all.

To do this I created the following initializer, with a simple but functional example:


module CustomMarkupHandler
MAPPINGS = {
`Chaining` =&gt; `Awesome`
}
def self.call(template)
begin
details = {
:locals =&gt; template.locals,
:virtual_path =&gt; template.virtual_path,
:updated_at =&gt; template.updated_at
}
updated_source = template.source
MAPPINGS.each_pair {|find, replace|
updated_source = updated_source.gsub(find, replace)
}
new_template = ActionView::Template.new(updated_source, template.identifier, template.handler, details)
rescue
new_template = template
end
ActionView::Template::Handlers::ERB.call(new_template)
end
end
# Custom Markup Language registration
ActionView::Template.register_template_handler :erb, CustomMarkupHandler
end

Note that if you copy and paste this code you’ll need to replace the backwards quote with a normal one – my syntax highlighter doesn’t like single or double quotes.

Let’s walk through what this is doing:

  1. It defines a custom markup handler module
    • Typically you’d want to look up the registered handler for a given extension, however since we are overriding the handler for ERB, we’ve hard coded it here to use ActionView::Template::Handlers::ERB.
    • The code here simply does a gsub BEFORE allowing ERB to process the source. Create any *.erb page with the word “Chaining” in it and it will be replaced at render time with “Awesome”.
      • Want a guru to validate this part – I believe that by adding this before the ERB process it should not interfere with the way that the file is cached and served back up later, thus retaining roughly the same performance that we had prior to this injection.
    • The source attribute of the ActionView::Template is read only so we copied out the attributes we needed (details, identifier, handler) and simply use them, along with our updated source, to create a new template.
    • We then can send our modified source template through the ERB handler for traditional markup. Since we ran our modifications before ERB we can easily gsub in method calls that will be handled as if they were in the file natively.
    • Finally, just in case something unexpected happens, the whole thing is wrapped in begin/rescue that will simply process the unadulterated template, hopefully preventing a 500 error.
  2. It registers the handler as the default handler for *.erb files
    • This means that ALL files ending in *.erb will be routed through this new handler instead.

Pele

He was a good dog.

January 1, 2000 – September 12, 2013.


Quitting, Per the Plan

Back in 2005 I had an idea to create a site that allows artists to sell their wares through the site, with me collecting a small fee for each sale. As I outline in this post, I made some mistakes in my approach that ultimately resulted in other companies beating me to market with the same idea. For a few years following I sporadically worked on the site and concept but never with any real vigor or drive.

About two years ago I decided that the idea still had merit but that I’d need to focus on a specific market that would give me an edge. Given that I planned on launching with my wood turning products and the fact that I know that art very well, I naturally decided to focus in on that niche. I put a plan into place for how I was going to market the site, how I was going to maintain it, and when I was going to call it quits.

To arrive at my plan I stepped back and asked myself what I wanted to achieve with the site. I decided that what I really wanted was an outlet to sell the products I make anyhow, while making a little bit of money, and the ability to allow other artists to do the same, should they choose to do so. It was never intended to be anywhere near capable of producing enough money to support me and could not interfere with my day job or family life.

Having that concept as my base, the rest of the planning was pretty easy:

  • I wanted the site to handle most of the day to day operations itself – sale notifications were automated, the site was designed so that customers could use self service features, other artists could interact through the site without my involvement (aside from the fee), etc. This would require a little bit more coding to automate some things that previously were manual, but not too much. In the end I basically had to drive products to the post office and the site handled the rest.
  • I wanted to limit the amount of money I put into it as I didn’t foresee a huge return. I arbitrarily landed on $500 seed money. Once that money was gone, no more could be put in. Any profit made from the site would be added to the pot as operating cash.
  • Once the money was gone OR one year passed by without starting to see at least a modest uptick in sales, I’d pull the plug. My choice which.

I was off and running.

As of today I am about a month shy of the 1 year mark. I’ve spent almost all of the money – a small chunk went to domain registration and hosting fees and the rest went to my marketing campaigns. The sales were able to cover the spread for a few months but haven’t averaged out enough to keep cash balances moving in the right direction. As of today, the site has $38.

So I’m sticking to the plan and calling it quits. Kind of.

I’ve been toying with the idea of pulling the plug for a few weeks now. While the site is pretty much fully automated, I still have to log in periodically to check security, logs, and other maintenance items, which takes up time that is in high demand right now. After thinking through the problems and my desire to still have an outlet to sell the art that I will make anyhow, I came to the realization that I should pull the plug on the site, but not the concept (yet).

I’ve decided to invest my remaining $38 into Etsy, the very company who beat me to the punch with the idea I was working towards back in 2005. With my product set it will cost me $7 to post my inventory for 4 months. If nobody buys anything at all, I can run Tanglewood for another 24 months ($38 / $7 = 6 payments [I’ll chip in a few bucks…]; 6 payments * 4 months each = 24 months) without having to worry about any sort of site maintenance at all.

Tonight I set up an Etsy storefront, shut Tanglewood Turnings down, and set up an automatic redirect from Tanglewood over to the Etsy storefront.

Was pulling the plug on my site hard? Of course. Was it the right decision? Absolutely. I made an objective line in the sand before I started and am sticking to it. Trying to trudge forward based on my emotional ties to what I’ve created simply doesn’t make sense. It isn’t hitting the business targets I set, thus it is failing. Bail out.

In this case I just happened to find an option that would allow me to extend the concept a little longer, while still not violating my objective exit strategy. The original Tanglewood site is sleeping now. In 24 months if I have no sales the Etsy Tanglewood store will be too.