Forum: Ruby on Rails One To Many To Many

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
De741cc66c97af5bc92345e216e9e5f0?d=identicon&s=25 Neal L (Guest)
on 2006-02-24 16:41
Hey all,

I'm trying to find a simple way to reference all of the objects that
belong to their parent's parent.  In other words:

Clients --> Orders --> LineItems

How do I get all of a client's lineitems in one array (i.e.,
client.all_lineitems)?

Thanks!
-Neal
17acfbd3a05cfb59e0543235cc0a813b?d=identicon&s=25 Joshua Susser (Guest)
on 2006-02-24 18:25
Neal L wrote:
> I'm trying to find a simple way to reference all of the objects that
> belong to their parent's parent.  In other words:
>
> Clients --> Orders --> LineItems
>
> How do I get all of a client's lineitems in one array (i.e.,
> client.all_lineitems)?

I'm assuming LineItem belongs_to :order and Order belongs_to :client.

If you are using Edge Rails, you can set this up as a
has_many...:through association, then you just say
client.orders.line_items and let Rails do the work for you.

If you're on 1.0, you can do this with some custom SQL:

in class LineItem...
def self.find_for_client(client)
  self.find_by_sql('SELECT DISTINCT li.* FROM clients c, orders o,
line_items li WHERE c.id = :client_id AND o.client_id = c.id AND
li.order_id = o.id', :client_id => client.id)
end

--josh
609e59bf8c5bfef51d142de60f1e5a2a?d=identicon&s=25 Jonathan Younger (Guest)
on 2006-02-24 18:58
(Received via mailing list)
I'm running Edge and client.orders.line_items does not work.

It returns:

 >> client.orders.line_items
NoMethodError: undefined method `line_items' for Order:Class

It would be awesome if this worked but it doesn't.

-Jonathan
17acfbd3a05cfb59e0543235cc0a813b?d=identicon&s=25 Joshua Susser (Guest)
on 2006-02-24 19:35
Jonathan Younger wrote:
> I'm running Edge and client.orders.line_items does not work.
>
> It returns:
>
>  >> client.orders.line_items
> NoMethodError: undefined method `line_items' for Order:Class

How about showing your class definitions with the has_many declarations?

If you're on Edge, assuming you have the right foreign keys in the
tables, you can do something like:

class Order < ActiveRecord::Base
 has_many :orders
 has_many :line_items, :through => :orders
 ...
end

Then you can do: client.line_items

--josh
609e59bf8c5bfef51d142de60f1e5a2a?d=identicon&s=25 Jonathan Younger (Guest)
on 2006-02-24 19:53
(Received via mailing list)
Right,

client.line_items works.
client.orders.line_items does not work. Your original example was for
client.orders.line_items.

It would be nice to be able to do client.orders.line_items.

It would be even nicer to traverse down to an arbitrary depth:

country = Country.find_by_name('United States')
country.states.clients.orders.line_items # Returns all of the line
items ordered in the United States. This is just an arbitrary example.

The SQL generated would look something like:

SELECT line_items.* FROM states LEFT JOIN clients ON states.id =
clients.state_id LEFT JOIN orders ON clients.id = orders.client_id
LEFT JOIN line_items ON orders.id = line_items.order_id WHERE
states.country_id = 1

-Jonathan
2d0f17b478aa748b34afec2e5ec07b8d?d=identicon&s=25 Anthony DeRobertis (Guest)
on 2006-02-24 20:44
(Received via mailing list)
Neal L wrote:

> Clients --> Orders --> LineItems

orders.map {|o| o.lineitems}

might work, though it'd generate a fair number of queries.

In SQL you could do:

SELECT li.* FROM
  clients c, orders o, lineitems li
 WHERE
  o.id = c.order_id AND li.id = c.lineitem_id
  AND c.id = ?

Assuming appropriate indices, this should even be relatively fast.


/me curses at rail's default id name breaking NATURAL JOIN
17acfbd3a05cfb59e0543235cc0a813b?d=identicon&s=25 Joshua Susser (Guest)
on 2006-02-24 20:59
Jonathan Younger wrote:
> client.line_items works.
> client.orders.line_items does not work. Your original example was for
> client.orders.line_items.
>
> It would be nice to be able to do client.orders.line_items.

D'oh!  You're right, that was a brain fart.  client.orders.line_items
won't work. It would be nice if the association was smart enough to do
that join for you using that syntax, wouldn't it? I wonder how hard it
would be to add that to the association magic?

--josh
This topic is locked and can not be replied to.