Simpe, but basic active record question

Hi,
I know i can do this:
if i have an ordeline i can do:

customername=orderline.order.customer.name

but can i also go the other way around?
lets say i have a customer and i want to get a hold of all orderlines

orderlines=customer.orders.orderlines would be great, but that doesn’t
work

is there a smart way to do this or do i have to use a plain sql query
like:

select customer from customers,orders,orderlines where
customer.customer_id=orders.customer_id and
orderline.order_id=order.order_id

the above doesn’t look very rails-like, thefore i am asking…

Remco

Remco Hh wrote:

Hi,
I know i can do this:
if i have an ordeline i can do:

customername=orderline.order.customer.name

but can i also go the other way around?
lets say i have a customer and i want to get a hold of all orderlines

orderlines=customer.orders.orderlines would be great, but that doesn’t
work

is there a smart way to do this or do i have to use a plain sql query
like:

select customer from customers,orders,orderlines where
customer.customer_id=orders.customer_id and
orderline.order_id=order.order_id

the above doesn’t look very rails-like, thefore i am asking…

Remco

As long as your associations are set up properly, you sure can do that.
However not exactly the way you expect.

customer.orders returns an array of orders, and an array does not have a
‘orderlines’ method. You should access it like this instead

customer.orders.each do |order|
do_something_with(order)
order.orderlines.each do |ol|
do_something_else_with(ol)
end
end

Or if you really want all the orderlines from all orders for a customer
lumped together in one big array, you can do:

orderlines = []
costomer.orders.each do |order|
orderlines += order.orderlines
end

Remco Hh <rails-mailing-list@…> writes:

orderlines=customer.orders.orderlines would be great, but that doesn’t
work

The problem is that customer.orders works, but returns a collection of
orders.
And a collection doesn’t have any orderlines.

A good bet would be customer.orders.collect{|o| o.orderlines} which
would
collect the orderlines from all of the orders and return them.

You’d end up with an array of arrays (this will only make sense in a
fixed width
font:)

------- order 1 ------- - order 2 - , ------------- order 3

[ [orderline1, orderline2], [orderline3], [orderline4, orderline5,
orderline6] ]

if you only want the orderlines then you can call
customer.orders.collect{|o| o.orderlines}.flatten which will collapse
the above
into one big array.

Thanks Gareth and Alex.

I get this, but i don’t really like it because if you compare it with
how i do it in the sql example, i only use one query with joines to get
the results. In your examples you create a loop (iterator) which submits
multiple queries

so, if there is no other method, i think i’ll just use plain old mysql
I was convinced rails had a better method…

regards,

remco

Alex W. wrote:

Remco Hh wrote:

Hi,
I know i can do this:
if i have an ordeline i can do:

customername=orderline.order.customer.name

but can i also go the other way around?
lets say i have a customer and i want to get a hold of all orderlines

orderlines=customer.orders.orderlines would be great, but that doesn’t
work

is there a smart way to do this or do i have to use a plain sql query
like:

select customer from customers,orders,orderlines where
customer.customer_id=orders.customer_id and
orderline.order_id=order.order_id

the above doesn’t look very rails-like, thefore i am asking…

Remco

As long as your associations are set up properly, you sure can do that.
However not exactly the way you expect.

customer.orders returns an array of orders, and an array does not have a
‘orderlines’ method. You should access it like this instead

customer.orders.each do |order|
do_something_with(order)
order.orderlines.each do |ol|
do_something_else_with(ol)
end
end

Or if you really want all the orderlines from all orders for a customer
lumped together in one big array, you can do:

orderlines = []
costomer.orders.each do |order|
orderlines += order.orderlines
end

Remco Hh wrote:

Thanks Gareth and Alex.

I get this, but i don’t really like it because if you compare it with
how i do it in the sql example, i only use one query with joines to get
the results. In your examples you create a loop (iterator) which submits
multiple queries

so, if there is no other method, i think i’ll just use plain old mysql
I was convinced rails had a better method…

regards,

remco

You can use eager loading to make so only one query is needed.

class Customer
has_many :orders, :include => :orderlines
end

This will put a LEFT OUTER JOIN in your SQL and fetch all associated
orderlines along with the orders. Then customer.order.first.orderlines
will not generate a query.

On 8/31/06, Remco Hh [email protected] wrote:

orderlines=customer.orders.orderlines would be great, but that doesn’t
work

customer.orders.orderlines.find(:all) may do the trick?

Isak

so, if there is no other method, i think i’ll just use plain old mysql
I was convinced rails had a better method…

If you need the lines for for a given order, why not just do something
like this:

@order = @customer.orders.find(order_id, :include => :order_lines)

That’ll use 1 query - the lines for that order will be accessible via
@order.order_lines.

Steve

Isak H. wrote:

On 8/31/06, Remco Hh [email protected] wrote:

orderlines=customer.orders.orderlines would be great, but that doesn’t
work

customer.orders.orderlines.find(:all) may do the trick?

Isak

i dont’t think this wil work…

If you really want to NOT loop on the orders, you could do the
following:

orders = Customer.orders.collect{|o| o.id}
lines = OrderLine.find(:all, :conditions => [‘order_id = (?)’,orders])

-Lonnie

Remco Hh wrote:

Thanks Gareth and Alex.

I get this, but i don’t really like it because if you compare it with
how i do it in the sql example, i only use one query with joines to get
the results. In your examples you create a loop (iterator) which submits
multiple queries

so, if there is no other method, i think i’ll just use plain old mysql
I was convinced rails had a better method…

regards,

remco