|
6 | 6 | # Example Schema |
7 | 7 | * User [id, name] |
8 | 8 | * Product [id, name, price] |
9 | | -* Order [id, user_id, date] |
10 | | -* OrderProduct [product_id, order_id] |
| 9 | +* Order [id, user\_id, date] |
| 10 | +* OrderProduct [product\_id, order\_id] |
11 | 11 |
|
12 | 12 | !SLIDE bullets |
13 | 13 | # Order Report Page |
14 | | -* Show all orders sorted by total cost |
| 14 | +* Show top ten orders sorted by total cost |
15 | 15 | * Show the user name, date, and total cost |
16 | 16 |
|
17 | 17 | !SLIDE |
18 | 18 | # Basic ActiveRecord |
19 | 19 | @@@ ruby |
20 | | - orders = Order.all |
21 | | - orders.sort! do |a,b| |
22 | | - a.products.inject(0){|p,s| s + p.price} <=> |
23 | | - b.products.inject(0){|p,s| s + p.price} |
| 20 | + o = Order.all |
| 21 | + o.sort! do |a,b| |
| 22 | + a.products.sum(&:price) <=> |
| 23 | + b.products.sum(&:price) |
24 | 24 | end |
25 | | - orders = orders[0..10] |
26 | | - orders.map do |order| |
27 | | - { |
28 | | - :user_name => order.user.name, |
| 25 | + o = o[0..10] |
| 26 | + o.map do |order| |
| 27 | + { :user_name => order.user.name, |
29 | 28 | :user_date => order.date, |
30 | | - :total_cost => order.products.inject(0){|p,s| s + p.price} |
| 29 | + :total_cost => |
| 30 | + order.products.sum(&:price) |
31 | 31 | } |
32 | 32 | end |
33 | 33 |
|
|
39 | 39 |
|
40 | 40 | !SLIDE |
41 | 41 | # First, join the tables |
42 | | - @@@ sql |
43 | | - SELECT users.name AS user_name, |
44 | | - orders.id AS order_id, |
45 | | - orders.date AS order_date, |
46 | | - products.id AS product_id, |
47 | | - products.price AS product_price |
48 | | - |
49 | | - FROM orders |
50 | | - JOIN orders_products ON |
51 | | - (orders_products.order_id = orders.id) |
52 | | - JOIN products ON |
53 | | - (orders_products.product_id = products.id) |
54 | | - JOIN users ON |
55 | | - (orders.user_id = users.id) |
| 42 | + @@@ ruby |
| 43 | + Order.select(%{ |
| 44 | + users.name as user_name, |
| 45 | + orders.id as order_id, |
| 46 | + orders.created_at as order_date, |
| 47 | + products.id as product_id, |
| 48 | + products.price as product_price |
| 49 | + }).joins(%{ |
| 50 | + join order_products on |
| 51 | + order_products.order_id = orders.id |
| 52 | + join products on |
| 53 | + order_products.product_id = products.id |
| 54 | + join users on orders.user_id = users.id |
| 55 | + }) |
56 | 56 |
|
57 | 57 | !SLIDE |
58 | 58 | # First, join the tables |
|
70 | 70 |
|
71 | 71 | !SLIDE |
72 | 72 | # Aggregate and sort |
73 | | - @@@ sql |
74 | | - SELECT users.name AS user_name, |
75 | | - orders.date AS order_date, |
76 | | - sum(products.price) AS total_cost |
77 | | - |
78 | | - FROM orders |
79 | | - JOIN orders_products ON |
80 | | - (orders_products.order_id = orders.id) |
81 | | - JOIN products ON |
82 | | - (orders_products.product_id = products.id) |
83 | | - JOIN users ON |
84 | | - (orders.user_id = users.id) |
85 | | - |
86 | | - GROUP BY orders.id, users.name, orders.date |
87 | | - ORDER BY total_cost DESC |
| 73 | + @@@ ruby |
| 74 | + Order.select(%{ |
| 75 | + users.name as user_name, |
| 76 | + orders.created_at as order_date, |
| 77 | + sum(products.price) as total_cost |
| 78 | + }).joins(%{ |
| 79 | + join order_products on |
| 80 | + order_products.order_id = orders.id |
| 81 | + join products on |
| 82 | + order_products.product_id = products.id |
| 83 | + join users on orders.user_id = users.id |
| 84 | + }).group('orders.id, user_name, order_date'). |
| 85 | + order('total_cost DESC') |
88 | 86 |
|
89 | 87 | !SLIDE |
90 | 88 | # Aggregate and sort |
|
105 | 103 | * Thus, prices are summed per-order |
106 | 104 |
|
107 | 105 | !SLIDE |
108 | | -# For ease of abstraction, make it a View |
109 | | - @@@ sql |
110 | | - CREATE VIEW order_costs AS |
111 | | - SELECT users.name AS user_name, |
112 | | - orders.date AS order_date, |
113 | | - sum(products.price) AS total_cost |
114 | | - FROM orders |
115 | | - JOIN orders_products ON |
116 | | - (orders_products.order_id = orders.id) |
117 | | - JOIN products ON |
118 | | - (orders_products.product_id = products.id) |
119 | | - JOIN users ON |
120 | | - (orders.user_id = users.id) |
121 | | - GROUP BY orders.id, users.name, orders.date |
122 | | - ORDER BY total_cost DESC |
| 106 | +# Make a view |
| 107 | + @@@ ruby |
| 108 | + Order.select(%{ |
| 109 | + users.name as user_name, |
| 110 | + orders.created_at as order_date, |
| 111 | + sum(products.price) as total_cost |
| 112 | + }).joins(%{ |
| 113 | + join order_products on |
| 114 | + order_products.order_id = orders.id |
| 115 | + join products on |
| 116 | + order_products.product_id = products.id |
| 117 | + join users on orders.user_id = users.id |
| 118 | + }).group('orders.id, user_name, order_date'). |
| 119 | + order('total_cost DESC').to_sql # <---- |
| 120 | + |
| 121 | +!SLIDE |
| 122 | +# Make a view |
| 123 | +### Copy that SQL into a migration |
| 124 | + @@@ ruby |
| 125 | + execute %{ |
| 126 | + CREATE VIEW order_costs AS |
| 127 | + SELECT |
| 128 | + users.name as user_name, |
| 129 | + orders.created_at as order_date, |
| 130 | + sum(products.price) as total_cost |
| 131 | + FROM "orders" join order_products on |
| 132 | + order_products.order_id = orders.id |
| 133 | + join products on |
| 134 | + order_products.product_id = products.id |
| 135 | + join users on orders.user_id = users.id GROUP BY orders.id, user_name, order_date ORDER BY total_cost DESC |
| 136 | + } |
123 | 137 |
|
124 | 138 | !SLIDE |
125 | | -# Now we can use the view in Rails |
| 139 | +# Views act like Models |
| 140 | +## Read Only |
126 | 141 | @@@ ruby |
127 | 142 | class OrderCost < ActiveRecord::Base |
128 | 143 | end |
|
0 commit comments