---
title: Constrain Yourself
teaser:
tags: web,rails,open source
author: Josh Clayton
published_on: 2012-05-08
---

Most Rails developers have written apps where you have a marketing homepage
and a route that you should be redirected to after signing in. There may even
be different pages to be redirected to after signing based on some sort of role
system.

Who wants to remember that route across the app? No one.

Instead of writing a nasty helper to determine where to send a user after
signing in, let's have Rails handle this for us.

Enter Rails routing constraints.

It turns out Rack is a beautiful piece of software! With Rails routing
constraints, we can re-use the Rails' `root` to handle all this logic for us.
This means no more remembering where `root_url` will take you or stuffing all
that logic into some giant switch statement!

For example, I recently wrote an app using Clearance and `high_voltage`. When
visiting the root path without being signed in, I wanted to render high
voltage's 'homepage' view. If the user was signed in, I wanted to display an
administrative page where they could manage their assets.

My routes file looks like this:

    root to: "assets#index", constraints: Clearance::SignedInConstraint
    root to: "high_voltage/pages#show", id: "homepage"

Two roots! My constraint to hitting assets#index is based off my class
`Clearance::SignedInConstraint`, which I've thrown in `lib/`.

```ruby
# lib/clearance/signed_in_constraint.rb
module Clearance
  class SignedInConstraint
    def self.matches?(request)
      request.env[:clearance].signed_in?
    end
  end
end
```

This looks to `request.env[:clearance]` (introduced in Clearance 0.13), which
returns a `Clearance::Session` instance, and allows us to call `#signed_in?`.

With Rails constraints, if `.matches?` returns true, the constraint is
fulfilled and the router allows assets#index to do its thing. When false, the
route 'falls through' and the next root kicks in.

Constraints are a great way to scope routes based on particular preconditions
and may end up cleaning up a handful of nasty conditional logic in a view
helper. Constraints can be great for things like subdomains as well, but I'd
love to hear about some more inventive uses.
