Rails Relationships


#1

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


#2

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


#3

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.


#4

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


#5

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


#6

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 :slight_smile:
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


#7

Neal 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.


#8

On 12/12/05, Juraci Krohling C. 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


#9

On 12/13/05, Santiago E. 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