One of the things you have to deal with when creating a rails app that faces “the public” is that you have to deal with meta data. Traditionally this would come down to a title, some keywords and a description. Currently meta tags are used for much more as both Open Graph and Twitter are using it to determine what to do when that link is shared. Making your site more SEO and social network friendly is not that straight forward as it used to be.
To say it is a big problem is sort of an over-statement. It’s more of a recurring issue within Ruby on Rails. In traditional view rendering in Rails there is a template file that is rendered through a layout template with the data provided by the controller. This is what Layout file could look like:
Document Title <%= yield %>
As you can see there is the <%= yield %> that contains the actual dynamic parts of this layout. But the title is also something you would like to control. Traditionally this is solved using a couple of custom helpers that set an instance variable from the view and place it in the layout during rendering. The basic principle is fine but it become more cumbersome when more data needs to be added to the “” of the document. Another option would be to use “extra” yields where you could do something like this in the view template:
<% content_for :head do %>Other Document Title <% end %>
and in the layout:
<%= yield :head %> <%= yield %>
This gives you ultimate control of your document head but there is no default to fall back upon and you would have to define it time and time again for every view. Repeating yourself in that way is never good.
Thinking about the problem I came up with some ideas how to solve this problem. Very crude solutions would be to use the double yield for the layout and have a partial rendered inside of it so you can re-use the code. But how do you deal with default values and overwriting them for a specific page? Helper methods could be a good solution but putting everything in the helper would be a lot of “bin code”. There is also the issue of data logic being put into the helpers if you take that route. The best solution in my opinion would be a hybrid solution. Using the design principles in our benefit. Decorators for data manipulation, Objects to contain and deal with the configurations and helper methods to input and output it in the views.
I’ve been tackling this problem a couple of times already on different projects and due to the nature of building software for different companies I had to do it again…. and again, and again. Although not the most efficient to spend my time it did give me several insights in how I could build it. And like John Cleese concluded in his talk about creativity I was able to improve the outcome drastically by having to start over again.
So what I did was make it one more time and now put it into a gem! It’s called Excalibur. The most recent details on how to use it and what you can do with it are on the page. But here are the basics:
It allows you to:
- Set global title and meta tags for your app.
- Add model specific configurations about what to use where.
- Simple helpers to initialize from the view and output it in the layout.
- Some extra candy to set things for a view without an object.
It could be a bit overkill if you’re not that much relying on SEO values of your pages or share-ability of your content but it does serve as a full form solution.
Excalibur is still under development but has already been running in production for several projects of mine and some other people. If you have any ideas, suggestions or anything else let me know or pass me a patch. I’m always open to suggestions!