Our latest Ruby on Rails front-end project strongly emphasizes a component-based approach. In this post, we briefly explain how a tiny helper not only helped us render UI components, but also resulted in better components thanks to well-defined contracts and effortless composition.
These days, most front-end developers agree that UIs should be built in a component-oriented fashion. If you’re curious about that larger conversation, there are plenty of good resources on that out there: We’d highly recommend the excellent Style Guide Podcast — yes, all twelve episodes are well worth listening to — as well as Atomic Design to get a sense of why this matters.
Implementing a component-based approach can be a challenge. Generally speaking, it’s a good idea to maintain an application-independent style guide / component library, not least because it tends to result in more well-crafted components (e.g. regarding documentation, reusability and robustness). These days, we can choose from numerous tools to set up a library like that (e.g. Pattern Lab or Fractal).
Even so, you probably still want some sort of abstraction to generate components' server-side markup1 within your application, both for convenience and encapsulation:
<image-gallery> here is a
which unobtrusively takes care of client-side augmentation.)
Whenever we need to generate such complex HTML structures within our templates, we just want to invoke something like a function with the respective parameters:
Well, that’s pretty much exactly what we’ve done in our latest project — which happens to use Haml (“HTML Abstraction Markup Language”), though this approach should work just the same with ERB or whatever templating language you prefer2:
Note that any parameters are passed in explicitly, which ensures that each component has a well-defined contract.
Components may also support blocks to allow for composition:
Behind the scenes,
component is just a tiny wrapper around the built-in
render Rails helper:
component is invoked, it renders the respective markup partial from
the corresponding directory in
app/components/image_gallery/_image_gallery.html.haml). That directory
typically also contains whatever else the component might require, such as CSS
We’d be happy to elaborate on that aspect some other time — let us know in the comments.
Distinguishing between server–side base markup and augmented client–side DOM structures improves performance, robustness and generally makes us a good citizen of the web — but that's a topic for another day. ↩
At least one of the authors is not particularly, err, partial to Haml. ↩
For this to work, we've extended
append_view_path Rails.root.join("app", "components"). ↩