# Rails Relationships

**URL:** <https://www.ruby-forum.com/t/rails-relationships/50053>\
**Category:** Rails\
**Created:** [December 12, 2005, 5:13pm UTC](https://www.ruby-forum.com/t/rails-relationships/50053 "2005-12-12T17:13:47Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![Neal](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/49beb7/32.png) [@Neal](https://www.ruby-forum.com/u/Neal)\
**Post date:** [December 12, 2005, 5:13pm UTC](https://www.ruby-forum.com/t/rails-relationships/50053/1 "2005-12-12T17:13:47Z")

</div>

I’m trying to find an elegant solution to a data model problem and was  
wondering if some of you good people could help. I’m setting up a  
simple book-loan tracking system, where an office has many people and  
people have many books. i.e.:

office --\> (has many) people --\> (has many) books

while office.people returns a list of people belonging to an office and  
people.books returns a list of books belonging to a person, is there a  
function such as office.books that would return all of the books  
belonging to all of the people in the office?

Thanks,  
-Neal

---

<div class="post-metadata">

**Author:** ![Neal](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/49beb7/32.png) [@Neal](https://www.ruby-forum.com/u/Neal)\
**Post date:** [December 12, 2005, 5:18pm UTC](https://www.ruby-forum.com/t/rails-relationships/50053/2 "2005-12-12T17:18:47Z")

</div>

I don’t think thats build in, but you could very easily define a method  
in office (books).

---

<div class="post-metadata">

**Author:** ![Neal](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/49beb7/32.png) [@Neal](https://www.ruby-forum.com/u/Neal)\
**Post date:** [December 12, 2005, 5:26pm UTC](https://www.ruby-forum.com/t/rails-relationships/50053/3 "2005-12-12T17:26:08Z")

</div>

Neal wrote:

> I’m trying to find an elegant solution to a data model problem and was  
> wondering if some of you good people could help. I’m setting up a  
> simple book-loan tracking system, where an office has many people and  
> people have many books. i.e.:
> 
> office --\> (has many) people --\> (has many) books
> 
> while office.people returns a list of people belonging to an office and  
> people.books returns a list of books belonging to a person, is there a  
> function such as office.books that would return all of the books  
> belonging to all of the people in the office?
> 
> Thanks,  
> -Neal

This may not be the most eligant solution but I would add a method to  
your ‘book’ model similar to this:

def self.find\_all\_by\_office\_id(office\_id)  
book\_collections = Person.find\_all\_by\_office\_id(office\_id).collect {  
|p| p.books }  
book\_collections.flatten!  
end

In a controller I would then use:

books\_by\_office = Book.find\_all\_by\_office\_id(office.id)

Hope this helps a bit.

---

<div class="post-metadata">

**Author:** ![Neal](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/49beb7/32.png) [@Neal](https://www.ruby-forum.com/u/Neal)\
**Post date:** [December 12, 2005, 5:30pm UTC](https://www.ruby-forum.com/t/rails-relationships/50053/4 "2005-12-12T17:30:48Z")

</div>

def books  
Book.find(:all, :conditions=\>[“person\_id IN (?)”,  
people.collect{|person| person.id}.join(", ")] ) ## not tested  
end

---

<div class="post-metadata">

**Author:** ![Neal](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/49beb7/32.png) [@Neal](https://www.ruby-forum.com/u/Neal)\
**Post date:** [December 12, 2005, 6:12pm UTC](https://www.ruby-forum.com/t/rails-relationships/50053/5 "2005-12-12T18:12:01Z")

</div>

Juraci Krohling C. wrote:

> def books  
> Book.find(:all, :conditions=\>[“person\_id IN (?)”,  
> people.collect{|person| person.id}.join(", ")] ) ## not tested  
> end

That function works great! Thanks!

How exactly is it joining the tables, though???

Thanks

---

<div class="post-metadata">

**Author:** ![Neal](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/49beb7/32.png) [@Neal](https://www.ruby-forum.com/u/Neal)\
**Post date:** [December 12, 2005, 6:27pm UTC](https://www.ruby-forum.com/t/rails-relationships/50053/6 "2005-12-12T18:27:59Z")

</div>

Er… its not joining… You cannot use :include in two level’s in  
ActiveRecord, but, I think the last thing you want to do w/ this method  
is something like this: office.books.people.books 🙂  
If you really need to join books w/ people in this method, uses this:

def books

Book.find(:all, :include=\>:person, :conditions=\>[“person\_id IN (?)”,  
people.collect{|person| person.id}.join(", ")] ) ## you told me this  
works =D

end

---

<div class="post-metadata">

**Author:** ![Neal](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/49beb7/32.png) [@Neal](https://www.ruby-forum.com/u/Neal)\
**Post date:** [December 12, 2005, 6:32pm UTC](https://www.ruby-forum.com/t/rails-relationships/50053/7 "2005-12-12T18:32:28Z")

</div>

Neal [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> Juraci Krohling C. wrote:
> 
> > def books  
> > Book.find(:all, :conditions=\>[“person\_id IN (?)”,  
> > people.collect{|person| person.id}.join(", ")] ) ## not tested  
> > end
> 
> That function works great! Thanks!
> 
> How exactly is it joining the tables, though???

The “join” message is not an SQL join operation. It is a collection  
method that joins all the items in a collection into a string, separated  
by in this case a comma. What that code does is fetches all the books  
that belong to any person in that office by filtering on the person\_id  
value of the book, where the people collection equals office.people.  
There is of course a way to do that all in SQL - you’ll have to decide  
which approach is better for your uses.

---

<div class="post-metadata">

**Author:** ![Neal](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/49beb7/32.png) [@Neal](https://www.ruby-forum.com/u/Neal)\
**Post date:** [December 13, 2005, 12:16pm UTC](https://www.ruby-forum.com/t/rails-relationships/50053/8 "2005-12-13T12:16:06Z")

</div>

On 12/12/05, Juraci Krohling C. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> def books  
> Book.find(:all, :conditions=\>[“person\_id IN (?)”,  
> people.collect{|person| person.id}.join(", ")] ) ## not tested  
> end

I’m trying to use this method but I have a problem. This inserts  
everything like a string example … IN (‘1,3’)

Is there any way to avoid rails to add those quotes?

Thanks,  
Santiago

---

<div class="post-metadata">

**Author:** ![Neal](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/49beb7/32.png) [@Neal](https://www.ruby-forum.com/u/Neal)\
**Post date:** [December 13, 2005, 12:31pm UTC](https://www.ruby-forum.com/t/rails-relationships/50053/9 "2005-12-13T12:31:09Z")

</div>

On 12/13/05, Santiago E. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> Is there any way to avoid rails to add those quotes?
> 
> Thanks,  
> Santiago

OK, I solved this by myself.

Book.find(:all, :conditions=\>“person\_id IN #{people.collect{|person|  
person.id}.join(', ')}”)

Santiago
