---
title: Tips For Writing Your Own Rails Engine
teaser:
tags: web,ruby,rails
author: Dan Croak
published_on: 2009-04-23
---

While converting [Clearance to a Rails engine][converting] was easy, once we
were there, we found it wasn't Valhalla.

[converting]: https://thoughtbot.com/blog/2009/4/22/clearance-is-a-rails-engine

![Viking Funeral](http://images.thoughtbot.com/ui/2009-4-22-viking_funeral.jpg)

We fixed the bugs while using the engine internally on a few apps. Here
are the lessons we learned. Keep them in mind if you're thinking of writing
your own engine.

<object width="425" height="344">
  <param name="movie"
    value="http://www.youtube.com/v/tSHM5FiOChY&amp;hl=en&amp;fs=1" />
  <embed src="http://www.youtube.com/v/tSHM5FiOChY&amp;hl=en&amp;fs=1"
    type="application/x-shockwave-flash" width="425" height="344" />
</object>

## Routes precedence

As developers, we want **routes in our app to take precedence over routes in the
engine**. That is not the default behavior.

To get around that, we came up with this hack. (credit to Nick Quaranto, a.k.a.
qrush a.k.a. Internbot)

```ruby
class ActionController::Routing::RouteSet
  def load_routes_with_clearance!
    clearance_routes = File.join(File.dirname(__FILE__),
                        *%w[.. config clearance_routes.rb])
    unless configuration_files.include? clearance_routes
      add_configuration_file(clearance_routes)
    end
    load_routes_without_clearance!
  end

  alias_method_chain :load_routes!, :clearance
end
```

Rather than using the Rails engine convention of naming the routes file
`vendor/gems/clearance/config/routes.rb`, we named it
`vendor/gems/clearance/config/clearance_routes.rb` so it won't be automatically
loaded. Then we `alias_method_chain` around some `ActionController` internals.

Ugly stuff, but effective and solved a blocker for releasing as an engine.

## Cached classes in development

In development, all your classes are constantly reloaded. This makes sense for
your app, but not for your engine classes or modules.

We added
[unloadable](http://apidock.com/rails/ActiveSupport/Dependencies/Loadable/unloadable)
to our `Clearance` module to fix this. Again, credit goes to Nick.

```ruby
class Clearance::SessionsController < ApplicationController
  unloadable
end
```

If you see errors like the following, you might consider a similar approach.

    has been removed from the module tree but is still active

## Namespacing controllers

We decided namespacing controllers was a good convention for our engine.

When we need to override something in the engine, this gives us clear routes
separation...

```ruby
# in the engine
ActionController::Routing::Routes.draw do |map|
  map.resources :users, :controller => 'clearance/users' do |users|
    users.resource :password,
      :controller => 'clearance/passwords',
      :only => [:create, :edit, :update]
end

# in the app
ActionController::Routing::Routes.draw do |map|
  map.resources :users
end
```

... and clean subclassing:

```ruby
class UsersController < Clearance::UsersController
  def edit
    ...
  end
end
```

## Helper inclusion

Tammer has also recently been extracting the announcement code from
[Hoptoad](http://hoptoadapp.com) into an engine. He found that `helper :all` in
the controller doesn't find engine helpers.

Within the engine's `init.rb`, he hooked his engine's `AnnouncementsHelper` into
the app's `ApplicationHelper` like so:

```ruby
config.to_prepare do
  ApplicationController.helper(AnnouncementsHelper)
end
```

Note that any code that extends classes from the application (such as
`ApplicationController`) must be wrapped in a `to_prepare` block.

This is because `ApplicationController` gets reloaded before each request during
development. Without this block, only the first request would see the
`AnnouncementsHelper` methods.
