The hokusai gem

inopinatus

Today I published the hokusai gem, a small Rails add-on for making templates from data. I was using the capability already for my main site, but extracted and gemified it after this discussion on the GoRails forums led me to think others might find it useful.

Usually when someone talks about templates in an MVC system they are referencing the view layer. However in this case, the templates are built for “stamping out” new copies of model data structures.

There’s some conceptual overlap with fixtures here, but fixtures in Rails are quite heavyweight and strongly oriented to being a test data factory. This gem is very lightweight, with only 62 lines of non-boilerplate code.

The name is a reference to a Japanese artist famous for his woodblock prints, including the iconic and instantly recognisable The Great Wave off Kanagawa. Woodblock prints are made by stamping a woodcut onto paper or fabric; this gem allows “stamping” a new object from a template. As a result this is my first recorded use of an emoji in library code 🌊 .

Purpose

A user, referring to some existing configuration of data, might have a request of this form:

“I want a new one just like that old one.”

This might involve making a deep clone of a bundle of associated models. Typically we’d write an application-specific deep copy method. But what if we need to save that for later? Perhaps for repeated use, or because the original might get deleted. In such cases you need to collect all the necessary data and persist it.

Here’s my ideal code for controlling such a feature:

template = Template.create!(origin: @project, name: "New template from project")

and then much later, this:

template = Template.find(params[:template_id])
@new_project = template.stamp do |project|
  project.name = "New project from template"
end

This gem makes such a simple interface possible even for models with many deep & complicated associations. I won’t repeat any more of the sample code in the README, suffice to say I’m already using it and I hope others will find it helpful.