Introducing Carpentry

Today we’re releasing one of the few gems that we use internally, making it available to everyone.
Carpentry is a tool that enables designers to focus on what they do best, without worrying about implementation details.

Workflow

Designers can now manage their own prototypes, without needing to worry where they are going to end up when implemented. Once ready, a developer will pick the file, move it to the appropriate place and wire it to the Rails application. Designers don’t need to care about controller design, and can try more in less time.

By default, prototypes are accessible when the application is deployed.
Now clients can see them and provide feedback before anything is implemented. If you don’t want prototypes available to everyone, don’t worry. There is an overridable before filter where anything can be added, such as authentication or a redirect if in production.

Getting started

To start using Carpentry, all you need to do is add it to the Gemfile and run rails generate carpentry:install.

The gem adds an directory (app/views/carpentry/prototypes) to a Rails project where prototype files go into, and makes them accessible at /p, following the same structure as the prototypes folder. So, if you have app/views/carpentry/prototypes/clients/new.html.haml you can access it at /p/clients/new.

Behind the scenes

Carpentry is not only useful, but it’s also available to prove a point.
Creating a Rails engine is easy, and a great way to extract functionality that is needed in several Rails applications. In fact, the whole gem has only 50 lines of code, including a Rack middleware, and a Rails generator.

Let’s take a look at the code.

First of all, there is the controller that catches all prototype requests and renders the correct file, in app/controllers/carpentry/prototypes_controller.rb:

We call the #before_carpentry before filter only if it is defined.
Since we inherit from ApplicationController, the method can be added there. The second argument in #respond_to? defines whether to look at private methods or not. In this case, we want that.

We also need to add a route to send the requests to our PrototypesController, in config/routes.rb:

Notice that we define that /p should render an index file if it exists, by setting the file_path parameter to index.

We configure our engine in lib/carpentry.rb so that Rails knows that our gem is an engine, and to use a middleware that we’re bundling with Carpentry:

Our NoRobotsMiddleware is very simple. It does nothing more than adding <meta name="robots" content="noindex, nofollow"/> before the end of the <head> tag so that prototypes don’t get crawled and indexed by search engines. The middleware is defined in lib/carpentry/no_robots_middleware.rb:

Hope this helps you understand how to build an engine. Look at the source code on GitHub and the specs we have if you’re building a small engine and don’t know where to look for examples.

If you’d like to learn more, you should probably get José Valim’s book Crafting Rails Applications.