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 -- Posted via http://www.ruby-forum.com/.
You can''t as far as I know... (someone correct me if I''m wrong
please...)
But you can make it work.
Not tested but it''s similar to something I did before.
In the client model, do this
def line_items
items = Array.new
for order in self.orders
items << order.line_items
end
items
end
Then you can do client.find(1).line_items
If that makes you cry because of performance reasons, then you might
want to replace that logic with a simple select statement and use
find_by_sql
-----Original Message-----
From: rails-bounces@lists.rubyonrails.org
[mailto:rails-bounces@lists.rubyonrails.org] On Behalf Of Neal L
Sent: Friday, February 24, 2006 9:41 AM
To: rails@lists.rubyonrails.org
Subject: [Rails] One To Many To Many
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
--
Posted via http://www.ruby-forum.com/.
_______________________________________________
Rails mailing list
Rails@lists.rubyonrails.org
http://lists.rubyonrails.org/mailman/listinfo/rails
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 -- Posted via http://www.ruby-forum.com/.
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 On Feb 24, 2006, at 9:25 AM, Joshua Susser wrote:> 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.-------------- next part -------------- An HTML attachment was scrubbed... URL: http://wrath.rubyonrails.org/pipermail/rails/attachments/20060224/3a77b88d/attachment.html
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:ClassHow 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 -- Posted via http://www.ruby-forum.com/.
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
On Feb 24, 2006, at 10:35 AM, Joshua Susser wrote:
> 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
>
> --
> Posted via http://www.ruby-forum.com/.
> _______________________________________________
> Rails mailing list
> Rails@lists.rubyonrails.org
> http://lists.rubyonrails.org/mailman/listinfo/rails
Neal L wrote:> Clients --> Orders --> LineItemsorders.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
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 -- Posted via http://www.ruby-forum.com/.