# ActiveRecord: Least surprise? Really?

**URL:** <https://www.ruby-forum.com/t/activerecord-least-surprise-really/158770>\
**Category:** Rails\
**Created:** [January 27, 2009, 8:35pm UTC](https://www.ruby-forum.com/t/activerecord-least-surprise-really/158770 "2009-01-27T20:35:38Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![casper\_the\_ghost](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/58956e/32.png) [@casper\_the\_ghost](https://www.ruby-forum.com/u/casper_the_ghost)\
**Post date:** [January 27, 2009, 8:35pm UTC](https://www.ruby-forum.com/t/activerecord-least-surprise-really/158770/1 "2009-01-27T20:35:38Z")

</div>

OK I AM new to RoR, and I have more experience with Java and straight  
SQL. So maybe I’m just so used to thinking in a way that is  
anticipating more than “least” surprise. Anyway, here’s what  
surprised me:

If I have an object that belongs to another object, I would expect the  
parent to have the FK to the child, not the other way around.

Why? Because if I were to do it in memory (forget about persistence  
for a minute), it would like kinda like this:

p = Parent.new  
p.children \<\< Child.new

Now in this example, p has an array of children (as in, it HAS MANY).  
If I wanted to do a two-way relationship, I would do:

p = Parent.new  
c = Child.new  
p.children \<\< c  
c.parent = p

In this case, the parent has an array of children (literally a list of  
many references to its children), and the child has a single reference  
to a parent (assuming an xml-like hierarchy here, not a family-tree  
type hierarchy).

Anyway, when I create a “has\_one” association, I would expect this  
object’s table to literally have a FK column for the “child” object.  
When I create a “belongs\_to” association, I would expect the same  
thing.

When I create a “has\_many” association, I would expect a fact table  
“parent\_child” to be created (with id, parent\_id, and child\_id  
columns), and if I wanted a two-way relationship, I would add  
“belongs\_to” to the Child.

* * *

What’s my point?  
Glad you asked.

If I wanted to create a class that maintains various user lists:  
class UserLists \< ActiveRecord::Base  
has\_many :naughty, :class =\> “User”  
has\_many :nice, :class =\> “User”  
has\_many :absent, :class =\> “User”  
end

## I would expect some fact tables to be created: naughty\_users (with columns id, userlist\_id, user\_id), nice\_users (with id, userlist\_id, user\_id), and absent\_users (again with id, userlist, and id).

Could someone set my thinking straight here? Maybe I just need a  
little explanation around best practices or something…

---

<div class="post-metadata">

**Author:** ![casper\_the\_ghost](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/58956e/32.png) [@casper\_the\_ghost](https://www.ruby-forum.com/u/casper_the_ghost)\
**Post date:** [January 27, 2009, 9:02pm UTC](https://www.ruby-forum.com/t/activerecord-least-surprise-really/158770/2 "2009-01-27T21:02:13Z")

</div>

> If I wanted to create a class that maintains various user lists:  
> class UserLists \< ActiveRecord::Base  
> has\_many :naughty, :class =\> “User”  
> has\_many :nice, :class =\> “User”  
> has\_many :absent, :class =\> “User”  
> end
> 
> I would expect some fact tables to be created: naughty\_users (with  
> columns id, userlist\_id, user\_id), nice\_users (with id, userlist\_id,  
> user\_id), and absent\_users (again with id, userlist, and id).

has\_many :foo, :class =\> ‘User’ only says “find a model called User, and  
expect  
it to have a user\_list\_id pointing to us”.

To distinguish moral relevance, use:

has\_many :naughty, :class =\> ‘User’, :conditions =\> { :morality =\>  
'naughty }

Less mind-reading on AR’s part - it was not going to guess that  
User.naughty had  
a relationship with UserList#naughty, unless you specify that.

–  
Phlip

---

<div class="post-metadata">

**Author:** ![casper\_the\_ghost](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/58956e/32.png) [@casper\_the\_ghost](https://www.ruby-forum.com/u/casper_the_ghost)\
**Post date:** [January 28, 2009, 1:40am UTC](https://www.ruby-forum.com/t/activerecord-least-surprise-really/158770/3 "2009-01-28T01:40:36Z")

</div>

Steve H wrote:

> Could someone set my thinking straight here? Maybe I just need a  
> little explanation around best practices or something…

I’m having trouble following your logic.

Parent \< ActiveRecord::Base  
has\_many :children  
end

Child \< ActiveRecord::Base  
belongs\_to :parent  
end

A parent has many children and each child belongs to one a parent.

parent = Parent.find\_by\_name(“Bill”)  
parent.children.count  
=\> 0  
parent.children.build(:name =\> “Steve”);  
parent.children.count  
=\> 1  
steve = parent.children.find\_by\_name(“Steve”)  
steve.name  
=\> Steve

## Database:

parents  
|id|name|  
|1|Bill|

children  
|id|parent\_id|name|  
|id|1|Steve|

It all make perfect sense to me.

---

<div class="post-metadata">

**Author:** ![casper\_the\_ghost](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/58956e/32.png) [@casper\_the\_ghost](https://www.ruby-forum.com/u/casper_the_ghost)\
**Post date:** [January 28, 2009, 2:16am UTC](https://www.ruby-forum.com/t/activerecord-least-surprise-really/158770/4 "2009-01-28T02:16:10Z")

</div>

> When I create a “has\_many” association, I would expect a fact table  
> “parent\_child” to be created (with id, parent\_id, and child\_id  
> columns), and if I wanted a two-way relationship, I would add  
> “belongs\_to” to the Child.

I think you are getting your associations mixed up. In addition to the  
has\_many and belongs\_to associations, you can also have a  
has\_and\_belongs\_to\_many.

to use that one you would do this:

class User \< ActiveRecord::Base  
has\_and\_belongs\_to\_many :lists  
end

class List \< ActiveRecord::Base  
has\_and\_belongs\_to\_many :users  
end

and then you have a joining table, that if you stick to conventions,  
you call it:  
lists\_users

- user\_id
- list\_id

That is the simplest way to handle this, assuming you do not need to  
store any details about the membership.

Now if you need to store more details about the membership, then you  
would have three classes: User, List and Membership

class User \< ActiveRecord::Base  
has\_many :memberships  
end

class List \< ActiveRecord::Base  
has\_many :memberships  
end

class Membership \< ActiveRecord::Base  
belongs\_to :user  
belongs\_to :list  
end

Hope that helps. For the full API, go to,  
[http://rails.rubyonrails.com/classes/ActiveRecord/Associations/ClassMethods.html](http://rails.rubyonrails.com/classes/ActiveRecord/Associations/ClassMethods.html)

---

<div class="post-metadata">

**Author:** ![casper\_the\_ghost](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/58956e/32.png) [@casper\_the\_ghost](https://www.ruby-forum.com/u/casper_the_ghost)\
**Post date:** [January 28, 2009, 6:49am UTC](https://www.ruby-forum.com/t/activerecord-least-surprise-really/158770/5 "2009-01-28T06:49:26Z")

</div>

Philip, Robert, alberto, thanks for your replies!! They all helped  
and I do appreciate it.

It is making more sense now.

Cheers!

-Steve
