---
title: questioning one-to-ones
teaser:
tags: web,rails
author: Jared Carroll
published_on: 2007-10-29
---

I constantly find myself reviewing and questioning my domain model.  Recently I
noticed a pattern in 2 different webapps.

Here's the requirement from the client

> The web site has groups.  Each group has a forum.  Users can create and
> comment on posts in the forum.

A quick scan of that sentence finds 5 nouns we care about

1. Group
1. Forum
1. User
1. Post
1. Comment

Lets forget about modeling users for now and concentrate on the other 4.

```ruby
class Group < ActiveRecord::Base

  has_one :forum

  def before_create
    self.forum = Forum.new
  end

end

class Forum < ActiveRecord::Base

  belongs_to :group

  class << self

    def popular
    end

    def recent
    end

  end

end

class Post < ActiveRecord::Base

  belongs_to :forum
  has_many :comments

end

class Comment < ActiveRecord::Base

  belongs_to :post

end
```

database

    groups (id, name)
    forums (id, group_id)
    posts (id, title, body, forum_id)
    comments (id, body, post_id)

Thats a real simple schema (im still ignoring users for the time being as well
so no user_id in any table yet).

Looking at the requirement, finding the nouns and then creating classes for each
noun is a really simple modeling technique.  In this instance it yielded 4
classes (actually 5 but were ignoring users for now).

Now if an object has state usually I want to record this state in a table in the
db.  Looking at the schema for that `forums` table shows nothing but db keys, no
state at all.  I don't want tables in my db that are unnecessary so lets try to
get rid of it.

Looking back at our `Forum` model we see that it does have some useful behavior

```ruby
class Forum < ActiveRecord::Base

  belongs_to :group

  class << self

    def popular
    end

    def recent
    end

  end

end
```

It has 2 class side finders `#popular` and `#recent`.  I want to keep those.  In
ruby when we have behavior and no state we don't use classes, we use modules.

A forum is a discussion so we'll name our module along those lines

```ruby
module Discussable

  def self.included(clazz)
    clazz.has_many :posts
    clazz.extend ClassMethods
  end

  module ClassMethods

    def popular
    end

    def recent
    end

  end

end
```

Now let's mix this into our `Group` model and look at the domain model now

```ruby
class Group < ActiveRecord::Base

  include Discussable

end

class Post < ActiveRecord::Base

  belongs_to :group
  has_many :comments

end

class Comment < ActiveRecord::Base

  belongs_to :post

end
```

We've eliminated the `Forum` class and made a `Post` `belong_to` a `Group`
instead.  The interesting behavior that was in our old `Forum` class now resides
in the `Discussable` module which is then mixed into `Group`.

Let's look at some usage now.

Before we'd go

```ruby
Forum.popular
Forum.recent
```

Now we do

```ruby
Group.popular
Group.recent
```

That's going to be a problem once groups can be considered popular and recent by
means other than the activity in their forums.  That kind of makes me question
eliminating the `Forum` class.  I guess when that problem arises we could rename
those methods `#popular_forums` and `#recent_forums`.  In Ruby it is more
accurate to model behavior only classes using modules.  Once you need state with
your behavior then its time to use a class.

Classes like `Forum` are what I like to call container/collection classes.
These classes have no state and are used solely for managing a collection of
other objects, in the example above that would be a forum and its posts.  They
usually arise from over-modeling but sometimes they contain useful behavior.
Question these classes and see if you can eliminate them.

After some ask.com'ing i found some database design articles saying one to one
associations were indications of a poor design.

Thoughts?
