On Sundays I normally try to sit down and watch some football, but usually the computer is open and I’m watching my fantasy team lose fantastically while attempting to work between the distractions of the game. This is obviously not very productive so, on a recent Sunday, I decided to close the computer and just watch the games. I made a mistake.
I grabbed a notebook I had laying in front of me and started scribbling. I honestly don’t recall how it started, but I started jotting down some Haml and began asking myself questions like “why do I need to code the for loops?”. Haml is so far away from HTML I was wondering why not take the extra steps and make it smarter? Why couldn’t there be an attribute like :collection, that could tell Haml to repeat the contents for each item of the collection, roughly like:
%ul{:collection => users}
%li
= first_name
I quickly then jumped to why can’t I just do this in HTML, again, roughly like:
<ul ruby="collection: users">
<li ruby="first_name"> User's First Name</li>
</ul>
I immediately started digging into this idea and quickly created a core list of keywords that could provide some core functionality:
- _if: for conditional execution
- _unless: for conditional execution
- _collection: for looping
With this core functionality in place, I did a brief announcement and had some great conversations. Peter Cooper suggested the move from ruby to data-ruby for HTML5 compliance and then the suggestion was made to move from data-ruby to data-ruhl to protect against potential naming collisions. More great conversations followed, one thing led to another and before I knew it, RuHL was officially born.
I didn’t have huge plans for this, I just wanted to see if I could pull off Haml/Erb functionality with just the data-ruhl attribute. While I wasn’t sure where this was going, I knew I wanted to stick with this idea because I believe code in views is bad and this didn’t open the view like other template languages.
To this point, the data-ruhl attribute simply calls methods. Instance variables were initially supported, but it became clear that they promoted more code and therefore were removed. This strengthened the belief that opening up your view to code encourages bad design.
With this thought in mind, I started reviewing a bunch of views to see what would have to change. It was a lot and in order for RuHL to pull this off, the presenter pattern would have to be implemented.
This was not a comfortable change for me and I didn’t know if RuHL was a viable option at first, but I stuck to the belief that “code in views is bad” is correct. I’m pleased I did because employing the presenter pattern has resulted in very clean code. This separation of code from the view separates testing and this has been very good indeed.
Here’s where I think it really gets interesting. What if the difficulty with view testing has been due to the fact that views are coded wrong? When writing tests for controllers, it’s generally accepted that bad controller code complicates your tests and therefore makes them difficult. In order to avoid these headaches, people have learned that skinny controllers are good. Why haven’t we learned the same lesson with testing views?
Using the presenter pattern pushes logic into classes that are much easier to test and doesn’t require passing through controller methods to setup the various testing scenarios. My view tests can be simplified to check for the correct data-ruhl attributes and to do this I don’t have to render my views, I can just parse them with Nokogiri. Since these attributes call the methods that are covered in my presenter tests, I’m pretty well covered.
I’m still putting RuHL to real world tests and refining the library as use cases arise. If you’ve had the same thought over the years and don’t mind HTML, give RuHL a shot.
