---
title: true or false
teaser:
tags: web,rails
author: Jared Carroll
published_on: 2007-04-25
---

"We'll just add a flag in the database."

I hate that phrase, it just sounds like a hack.  I've seen databases with tables
that are nothing but flags.  You just know that all through the code are a bunch
of `if` statements, conditionally doing all kinds of things on those flags.

So a while ago, I decided to pretend databases didn't support boolean data
types.  I refused to add any more flags to my tables, and instead make classes
out of each of the flags.

For example, say we have users who have to confirm their account before they can
log into the site.

Instead of this:

```ruby
class User < ActiveRecord::Base
end
```

and the table:

```sql
users (id, name, confirmed, confirmed_on) -- We also want the time when they
-- confirmed their account
```

We have this:

```ruby
class User < ActiveRecord::Base
  has_one :confirmation
end

class Confirmation < ActiveRecord::Base
  belongs_to :user
end
```

And our tables:

```sql
users (id, name)
confirmations (id, user_id, created_on)
```

In my mind, this was good because by using Rails' `created_on` attribute I could
get the confirmation timestamp for free.  I no longer had to write something
like this in my code:

```ruby
user.confirmed_on = Time.now
```

After doing this for a couple of states, I realized this was dumb.  I just
created a bunch of classes that had no interesting behavior, and complicated all
my queries with joins.  So I refactored the code back, to use flags in the
`users` table.  This was much simpler and better.

But what if some object's behavior depended on what state it was currently in?

For example, say we have documents that start out in a draft state, move to a
reviewed state and then finally to a published state.  And what differs in each
state is the validation that's performed when you attempt to save the document.
So the validation that gets performed on a document depends on its current
state.

Let's create a class for each state to be responsible for the state specific
validation, and let the document collaborate with them.  Forget about the
specifics for each state's validation, I'm going to just make up some
differences.

So we've got:

```ruby
class Document < ActiveRecord::Base

  has_one :state

  validates_associated :state

  def before_validation_on_create
    # apparently Rails does not set the foreign key until after validation
    self.state = Draft.new :document => self
  end

end

class State < ActiveRecord::Base

  belongs_to :document

  def validate
    raise NoMethodError,
      'Must be implemented by subclasses to perform state specific validation'
  end

end

class Draft < State

  # in a draft state, documents must have a title
  def validate
    if document.title.blank?
      document.errors.add :title, "can't be blank"
    end
  end

end

class Reviewed < State

  # in a reviewed state, documents must have a grade (A, B, C, etc.)
  def validate
    if document.grade.blank?
      document.errors.add :grade, "can't be blank"
    end
  end

end

class Published < State

  # in a published state, documents must have a license (Creative Commons, etc.)
  def validate
    if document.license.blank?
      document.errors.add :license, "can't be blank"
    end
  end

end
```

So whenever a `Document` is first created, we put it automatically in a `Draft`
state in the `Document`'s `#before_validation_on_create` callback.  And
somewhere we have a form that POSTs to an action in some controller to allow
someone to change a `Document`'s state:

```ruby
# POST id=1&state=Reviewed
def update
  @document = Document.find params[:id]
  # same hack as in Document#before_validation_on_create
  @document.state = params[:state].constantize.new :document => @document
  if @document.save
    redirect_to document_path(@document)
  else
    render :action => :edit
  end
end
```

(`#constantize` is a Rails helper method that will turn a String into its
corresponding class object, e.g. `Reviewed.constantize` returns the `Reviewed`
class object.)

We use Rails' `#validates_associated` to automatically validate the `Document`'s
associated `State` object (i.e. send it `#validate`) in order to perform the
state specific validation whenever a `Document` is saved.

Let's take a step back and look at this code.  So we've got `Document`, that's
fine and 4 `State` classes.  Do we need those 4 `State` classes?  I mean all
we're doing is validation, if there were more interesting behavior maybe they'd
be justified but let's try to get rid of them.

So instead of using classes to represent states, let's use boolean flags.

Our schema goes from:

```sql
documents (id, title, body, grade, license)
states (id, type, document_id)
```

to this:

```sql
documents (id, title, body, grade, license, draft, reviewed, published)
-- draft, reviewed and published are flags
```

In our `State` classes, it felt weird to write code like this:

```ruby
if document.title.blank?
  document.errors.add :title, "can't be blank"
end
```

Because that's exactly what
`ActiveRecord::Validations::ClassMethods#validates_presence_of` does for us for
free (including the error messages).  I know we can reuse
`#validates_presence_of` somehow.

Now looking at the Rails' doc for `#validates_presence_of` I see it takes an
`if` keyword parameter that determines if the validation should proceed.  I
think that's what were looking for.

Let's refactor this trash:

```ruby
class Document < ActiveRecord::Base
  validates_presence_of :title, :if => :draft?
  validates_presence_of :grade, :if => :reviewed?
  validates_presence_of :license, :if => :published?

  def before_validation_on_create
    self.draft = true
  end
end
```

Now that's better.  `#validates_presence_of`'s `if` keyword parameter gives us our
state specific validation.

And that controller action to update a `Document` object's state becomes:

```ruby
# POST id=1&reviewed=1
def update
  @document = Document.find params[:id]
  if @document.update_attributes params[:document]
    redirect_to document_path(@document)
  else
    render :action => :edit
  end
end
```

Boilerplate and simple.  The rewritten version gets rid of that `:document =>`
hack in order to force the association before validation takes place:

In the action I had:

```ruby
@document.state = params[:state].constantize.new :document => @document
```

And in `Document#before_validation_on_create`:

```ruby
self.state = Draft.new :document => self
```

I didn't like that hack, so I'm glad I was able to get rid of it (If anyone
knows a workaround I'd be glad to try it out).

So at first, I implemented the various states a `Document` could be in using
classes, just like I did my `User` `Confirmation` feature because I didn't want
to use boolean flags in my database.  Then I decided that boolean flags are all
right, and simplified the code a lot by eliminating 4 classes.  The first design
was an implementation of the classic GoF State pattern but in this situation the
State pattern is almost supported by Rails by using `#validates_presence_of`'s
`if` keyword parameter.  That's not to say the first implementation is not
applicable in Rails, it's just that in this example that only dealt with simple
validation, it wasn't appropriate.  If each state had a lot more complex
validation and/or interesting behavior, then I would support the first
implementation of using classes for each state.
