How can I join these tables?

A bit of a re-post, but I’ve cleaned up the question.

–MODELS–
class Unit < ActiveRecord::Base
has_many :rooms

class Room < ActiveRecord::Base
belongs_to :unit
has_many :rentals
has_many :people, :through => :rentals

class Person < ActiveRecord::Base
has_many :rentals
has_many :rooms, :through => :rentals

class Rental < ActiveRecord::Base
belongs_to :room, :person

–QUESTION–
Using only the unit.id, how can I get the associated person.id?

Unit.find(id).room.rentals.each
{|r|
ids << r.people.id
}

this should work but you could always do individual finds

I slightly altered your instructions into:

def show
@unit = Unit.find(params[:id])
@rooms = @unit.rooms
@unit.room.rentals.each {|r| ids << r.people.id}
end

and get a nasty ‘undefined method `room’ for #Unit:0x4836e8c.’ I
though that @unit would be a class object, but that error implies that
it is just a boring old hash. However, even when I sub your code back
in:

def show
@unit = Unit.find(params[:id])
@rooms = @unit.rooms
Unit.find(params[:id]).room.rentals.each {|r| ids << r.people.id}
end

it gives me the same error, ‘undefined method `room’ for
#Unit:0x4812258.’ If I make a slight typographical edit to pluralize
rooms as:

Unit.find(params[:id]).rooms.rentals.each {|r| ids << r.people.id}

I get one step further but then Rails complains with, ‘undefined method
`rentals’ for Room:Class’ which implies that something is wrong with my
model associations. Any ideas?

hi,
what i understood and as far as my knowledge of rails goes
i tried this

Unit.find(unit.id).rooms.each do |x|
x.rentals.each do |y|
p Person.find(y.person_id)
end
end

gave results

regards
gaurav

On 11/14/06, Taylor S. [email protected] wrote:

and get a nasty ‘undefined method `room’ for #Unit:0x4836e8c.’

I am also kind of stuck here, you can do 2 thigns to check what’s
going wrong. Check the logs for the sql query that’s going to the db,
and see if that’s the one you want. 2. use the debug () function to
print the class of the result. some thing like this in your view <%=
debug(@unit) %>

I know these are not the answers, but it might some how lead to answers.

raj

Taylor S. wrote:

def show
@unit = Unit.find(params[:id])
@rooms = @unit.rooms
@unit.rooms.rentals.each {|r| ids << r.people.id}
end

This won’t work because @unit.rooms returns an array of rental objects,
and that array does not have a rentals method. If have to call the
association methods on the elements inside the rooms array, not on the
whole array itself. So iterate through them and collect the ids.

You need something more like this, with proper responsibilities broken
down between model, controller and view.

Unit model

def people
rooms.collect { |room| room.people }.flatten
end

Controller action

def show
@unit = Unit.find(params[:id])
end

View

<% @unit.people.each do |person| %>
<%= person.name %>

<% end %>

Raj: great tip on the ‘debug’ - it helped me understand what was being
created!
Gaurav: that works but doesn’t integrate with what I want to do.
Alex: iterating over rooms was my problem, thanks for fixing it! I
condensed your answer into what I think is the most graceful solution:

–CONTROLLER–

def show

#get the unit
@unit = Unit.find(params[:id])

#add the rooms
@rooms = @unit.rooms

#add the people
@rooms.collect { |room| room.people }

end

–VIEW–

<% for room in @rooms %>

#a bunch of room data

<% for person in room.people %>
<%= person.first_name + " " + person.last_name %>

<% end %>
<% end %>

The YAML file generated by ‘debug(@unit)’ helped me figure out the right
combination:

— !ruby/object:Unit
attributes:
common_room_width: “20”

floor_number: “1”
rooms:

  • !ruby/object:Room
    attributes:
    window_facing: E
width: "25"

people:

  • !ruby/object:Person
    attributes:
    occupation: steam engineer
 <SNIP>
  school1: none

THANKS EVERYONE!

On 11/14/06, Taylor S. [email protected] wrote:

has_many :people, :through => :rentals
Using only the unit.id, how can I get the associated person.id?

Person.find_by_sql(…)

AR finders don’t supplant SQL, think of them as convenience methods
for the simple cases…

Isak

Did you try:

class Unit < ActiveRecord::Base
has_many :rooms
has_many :renters, :through => :rooms, :source => :people

And then do a Unit.find(:first).renters for a list of people that are
renting in that unit?

-christos

Unit.find(id).room.rentals.each
{|r|
ids << r.people.id
}

your error was ‘room’ is unidentified method so how about ‘rooms’

Unit.find(id).rooms.rentals.each
{|r|
ids << r.people.id
}