zer0uno
zer0uno

Reputation: 8030

Deeper knowledge about ActiveRecord

I'll try explain my doubt starting from the beginning. I have the following tables:

carts
+----+-------------------------+-------------------------+
| id | created_at              | updated_at              |
+----+-------------------------+-------------------------+
| 1  | 2013-11-09 12:57:37 UTC | 2013-11-09 12:57:37 UTC |
| 2  | 2013-11-10 11:33:25 UTC | 2013-11-10 11:33:25 UTC |
| 3  | 2013-11-10 12:16:25 UTC | 2013-11-10 12:16:25 UTC |
+----+-------------------------+-------------------------+


line_items
+----+------------+---------+-------------------------+-------------------------+----------+
| id | product_id | cart_id | created_at              | updated_at              | quantity |
+----+------------+---------+-------------------------+-------------------------+----------+
| 1  | 2          | 2       | 2013-11-10 11:33:25 UTC | 2013-11-10 11:33:25 UTC | 1        |
| 2  | 2          | 2       | 2013-11-10 11:45:26 UTC | 2013-11-10 11:45:26 UTC | 1        |
| 3  | 5          | 2       | 2013-11-10 11:46:06 UTC | 2013-11-10 11:46:06 UTC | 1        |
| 4  | 2          | 2       | 2013-11-10 12:08:41 UTC | 2013-11-10 12:08:41 UTC | 1        |
| 5  | 5          | 2       | 2013-11-10 12:09:03 UTC | 2013-11-10 12:09:03 UTC | 1        |
| 6  | 5          | 2       | 2013-11-10 12:15:48 UTC | 2013-11-10 12:15:48 UTC | 1        |
| 7  | 2          | 3       | 2013-11-10 12:16:26 UTC | 2013-11-10 12:16:26 UTC | 1        |
| 8  | 2          | 3       | 2013-11-10 12:29:21 UTC | 2013-11-10 12:29:21 UTC | 1        |
+----+------------+---------+-------------------------+-------------------------+----------+

I execute the following statements:

cart = Cart.find(2)
sums = cart.line_items.group(:product_id).sum(:quantity)

The result is the following: => {2=>3, 5=>3}
Untill here I have to say that it seemed to me pretty clear, that is I calculate the sums of the products based on the product id and then I collapse same products.
The doubts came later, when I tried to break up the instruction cart.line_items.group(:product_id).sum(:quantity)
I followed the following steps:

cart = Cart.find(2)
items = cart.line_items.group(:product_id)

and I got:

+----+------------+---------+-------------------------+-------------------------+----------+
| id | product_id | cart_id | created_at              | updated_at              | quantity |
+----+------------+---------+-------------------------+-------------------------+----------+
| 4  | 2          | 2       | 2013-11-10 12:08:41 UTC | 2013-11-10 12:08:41 UTC | 1        |
| 6  | 5          | 2       | 2013-11-10 12:15:48 UTC | 2013-11-10 12:15:48 UTC | 1        |
+----+------------+---------+-------------------------+-------------------------+----------+

and finally I executed items.sum(:quantity) and here, with my surprise, I got again=> {2=>3, 5=>3}
I came in doubt because I can't understand how I could get for each product id a number of quantity equals to 3 if I executed my sum on an object (items) which contains only 2 rows and for each one the quantity is 1.
What does items memorize? The object obtained from cart.line_items.group(:product_id) or and SQL string which means that everytime I interact with items I interact with my database? I am getting a lit bit confused.

Upvotes: 1

Views: 60

Answers (1)

Peter Alfvin
Peter Alfvin

Reputation: 29389

Good questions. :-)

items is an ActiveRecord::Relation which represents a query. Not all operations on that object result in another database operation, but some do. For example, length and to_a do not access the database again, but count does.

Relations are also "chainable", so when you call items.sum(:quantity) it builds a new relation. In other words, a relation can be thought of both as a query and the results from executing that query. When you chain methods, you're really operating on the query component, not the intermediate results.

Upvotes: 3

Related Questions