You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: rails6/en/chapter00-before.adoc
+2Lines changed: 2 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -31,3 +31,5 @@ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMP
31
31
****
32
32
33
33
"API on Rails 6" by https://github.com/madeindjs/api_on_rails[Alexandre Rousseau] is shared according to http://creativecommons.org/licenses/by-sa/4.0/[Creative Commons Attribution - Attribution-ShareAlike 4.0 International]. Built upon this book http://apionrails.icalialabs.com/book/.
34
+
35
+
Book's cover picture use a beautiful photo shot by https://unsplash.com/@siloine?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText[Yoann Siloine] who published it on https://unsplash.com[Unsplash].
Copy file name to clipboardExpand all lines: rails6/en/chapter07-placing-orders.adoc
+31-44Lines changed: 31 additions & 44 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,20 +1,21 @@
1
1
[#chapter07-placing-orders]
2
2
= Placing Orders
3
3
4
-
In previous chapter we handle associations between product and user models, and how to serialize them in order to scale fast and easy. Now it is time to start placing orders which is going to be a more complex situation. We will handle associations between three models and we have to be smart enough to handle the JSON output we are delivering.
4
+
In previous chapter we handle associations between products and users and how serialize them in order to scale fast and easy. Now it is time to start placing orders which is going to be a more complex situation. We will handle associations between thesesthree models. We have to be smart enough to handle the JSON output we are delivering.
5
5
6
6
In this chapter we will make several things which I list below:
7
7
8
8
* Create an `Order` model with its corresponding specs
9
9
* Handle JSON output association between the order user and product models
10
10
* Send a confirmation email with the order summary
11
11
12
-
So now everything is clear, we can get our hands dirty. You can clone the project up to this point with:
12
+
So now everything is clear we can get our hands dirty. You can clone the project up to this point with:
13
13
14
14
[source,bash]
15
15
----
16
16
$ git checkout tags/checkpoint_chapter07
17
17
----
18
+
18
19
Let’s create a branch to start working:
19
20
20
21
[source,bash]
@@ -24,23 +25,23 @@ $ git checkout -b chapter07
24
25
25
26
== Modeling order
26
27
27
-
If you remember associations model, the `Order` model is associated with users and products at the same time. It is actually really simply to achieve this in Rails. The tricky part is when comes to serializing this objects. I'll talk more about this in a next section.
28
+
If you remember associations model, `Order` model is associated with users and products at the same time. It is actually really simply to achieve this in Rails. The tricky part is when comes to serializing this objects. I'll talk more about this in a next section.
28
29
29
-
Let’s start by creating the order model, with a special form:
30
+
Let’s start by creating the order model with a special form:
30
31
31
32
[source,bash]
32
33
----
33
34
$ rails generate model order user:belongs_to total:decimal
34
35
----
35
36
36
-
The command above will generate the order model, but I’m taking advantage of the `references` method to create the corresponding foreign key for the order to belong to a user, it also adds the `belongs_to` directive into the order model. Let’s migrate the database.
37
+
The command above will generate the order model but I’m taking advantage of the `references` method to create the corresponding foreign key for the order to belong to a user. It also adds the `belongs_to` directive into the order model. Let’s migrate the database.
37
38
38
39
[source,bash]
39
40
----
40
41
$ rake db:migrate
41
42
----
42
43
43
-
Now it is time to drop some tests into the `order_test.rb` file:
44
+
Now it is time to write some tests into the `order_test.rb` file:
44
45
45
46
[source,ruby]
46
47
.test/models/order_test.rb
@@ -79,13 +80,13 @@ class User < ApplicationRecord
We need to setup the association between the `order` and the `product` and this is build with a `has-many-to-many` association. As many products will be placed on many orders and the orders will have multiple products. So in this case we need a model in the middle which will join these two other objects and map the appropriate association.
102
+
We need to setup the association between the `order` and the `product` and this is build with a *has-many-to-many* association. As many products will be placed on many orders and the orders will have multiple products. So in this case we need a model in the middle which will join these two other objects and map the appropriate association.
102
103
103
104
Let’s generate this model:
104
105
@@ -107,14 +108,14 @@ Let’s generate this model:
107
108
$ rails generate model placement order:belongs_to product:belongs_to
108
109
----
109
110
110
-
Let’s migrate the database:
111
+
Let’s run migration on database:
111
112
112
113
[source,bash]
113
114
----
114
115
$ rake db:migrate
115
116
----
116
117
117
-
The implementation is like so:
118
+
Implementation is like so:
118
119
119
120
[source,ruby]
120
121
.app/models/product.rb
@@ -138,7 +139,7 @@ end
138
139
----
139
140
140
141
141
-
If you have been following the tutorial so far the implementation is already there because of the `references` type we pass on the model command generator. We should add the inverse option to the `placement` model for each `belongs_to` call. This gives a little boost when referencing the parent object.
142
+
If you have been following the tutorial so far the implementation is already there because of the `references` type we pass on the model command generator. We should add `inverse_of` option to the `placement` model for each `belongs_to` call. This gives a little boost when referencing the parent object.
142
143
143
144
[source,ruby]
144
145
.app/models/placement.rb
@@ -155,7 +156,6 @@ Let’s run the _models_ spec and make sure everything is green:
Up to this point and before start typing some code we have to ask ourselves:
187
187
188
-
> Should I leave my order endpoints nested into the `UsersController`, or should I isolate them?
188
+
> Should I leave my order endpoints nested into the `UsersController` or should I isolate them?
189
189
190
190
The answer is really simple: it depends on the amount of information you want to expose to the developer.
191
191
@@ -217,7 +217,7 @@ class Api::V1::OrdersControllerTest < ActionDispatch::IntegrationTest
217
217
end
218
218
----
219
219
220
-
If we run the test suite now, as you may expect, both tests will fail, because they have not even set the correct routes, nor the action. So let’s start by adding the routes:
220
+
If we run the test suite now both tests should fail as you may expect. This is because they have not even set the correct routes nor actions. So let’s start by adding the routes:
221
221
222
222
[source,ruby]
223
223
.config/routes.rb
@@ -232,7 +232,6 @@ Rails.application.routes.draw do
232
232
end
233
233
----
234
234
235
-
236
235
Now it is time for the orders controller implementation:
237
236
238
237
[source,bash]
@@ -266,8 +265,6 @@ class Api::V1::OrdersController < ApplicationController
266
265
end
267
266
----
268
267
269
-
270
-
271
268
And now all of our tests should pass:
272
269
273
270
[source,bash]
@@ -286,12 +283,12 @@ $ git add . && git commit -m "Adds the show action for order"
286
283
287
284
=== Render a single order
288
285
289
-
As you can already imagine, this route is very easy. We only have to set up a few configurations (routes, controller action) and this section will be over. We will also include products related to this order in the output JSON.
286
+
As you can already imagine this route is very easy. We only have to set up a few configurations (routes, controller action) and this section will be over. We will also include products related to this order in the output JSON.
class Api::V1::OrdersControllerTest < ActionDispatch::IntegrationTest
@@ -310,8 +307,6 @@ As you can see, the second part of the test verifies the product is included in
310
307
311
308
Let's add the implementation to run our tests. On the `routes.rb` file add the `show` action to the command routes:
312
309
313
-
314
-
315
310
[source,ruby]
316
311
.config/routes.rb
317
312
----
@@ -323,7 +318,7 @@ Rails.application.routes.draw do
323
318
end
324
319
----
325
320
326
-
And the implementation should look like this:
321
+
And implementation should look like this:
327
322
328
323
[source,ruby]
329
324
.app/controllers/api/v1/orders_controller.rb
@@ -344,7 +339,6 @@ class Api::V1::OrdersController < ApplicationController
344
339
end
345
340
----
346
341
347
-
348
342
Our tests should be all green:
349
343
350
344
[source,bash]
@@ -371,9 +365,15 @@ Before launching this feature, let's take the time to think about the implicatio
371
365
* decrease in product inventory
372
366
* add some validation for order placement to ensure that there are enough products at the time the order is placed
373
367
374
-
It seems like there's still a lot to do, but believe me: you're closer than you think and it's not as hard as it looks. For now, let's keep it simple and assume that we still have enough products to place any number of orders. We're just concerned about the server's response at the moment.
368
+
It seems like there's still a lot to do but believe me: you're closer than you think and it's not as hard as it looks. For now let's keep it simple and assume that we still have enough products to place any number of orders. We're just concerned about the server's response at the moment.
369
+
370
+
If you remember order model we need three things:
375
371
376
-
If you remember order model, we need three things: a total for the order, user who places the order and products for the order. Based on this information, we can start adding some tests:
372
+
* a total for the order
373
+
* user who places the order
374
+
* products for the order
375
+
376
+
Based on this information we can start adding some tests:
@@ -409,7 +409,7 @@ class Api::V1::OrdersControllerTest < ActionDispatch::IntegrationTest
409
409
end
410
410
----
411
411
412
-
As you can see we are creating a `order_params` variable with the order data. Can you see the problem here? If not, I’ll explain it later. Let’s just add the necessary code to make this test pass.
412
+
As you can see we are creating a `order_params` variable with the order data. Can you see the problem here? If not I’ll explain it later. Let’s just add the necessary code to make this test pass.
413
413
414
414
First we need to add the action to the resources on the routes file:
415
415
@@ -503,19 +503,6 @@ class Order < ApplicationRecord
503
503
end
504
504
----
505
505
506
-
Just before you run your tests, we need to update the `order` factory, just to make it more useful:
507
-
508
-
[source,ruby]
509
-
.spec/factories/orders.rb
510
-
----
511
-
FactoryBot.define do
512
-
factory :order do
513
-
user { nil }
514
-
total { 0.0 }
515
-
end
516
-
end
517
-
----
518
-
519
506
We can now hook the `set_total!` method to a `before_validation` callback to make sure it has the correct total before is validated.
520
507
521
508
[source,ruby]
@@ -527,7 +514,7 @@ class Order < ApplicationRecord
527
514
end
528
515
----
529
516
530
-
At this point, we are making sure the total is always present and bigger or equal to zero, meaning we can remove those validations and remove the specs. I’ll wait. Our tests should be passing by now:
517
+
At this point we are making sure the total is always present and bigger or equal to zero. This means we can remove those validations and remove the specs. I’ll wait. Our tests should be passing by now:
531
518
532
519
[source,bash]
533
520
----
@@ -593,7 +580,7 @@ class OrderMailerTest < ActionMailer::TestCase
593
580
end
594
581
----
595
582
596
-
I simply copied/pasted the tests from the documentation and adapted them to our needs. We must now ensure that these tests pass.
583
+
I simply copied/pasted tests from the documentation and adapted them to our needs. We must now ensure that these tests pass.
597
584
598
585
First, we add the method `OrderMailer#send_confirmation`:
599
586
@@ -610,7 +597,7 @@ class OrderMailer < ApplicationMailer
610
597
end
611
598
----
612
599
613
-
After adding this code, we must now add the corresponding views. It is a good practice including a text version in addition to the HTML version.
600
+
After adding this code we must add corresponding views. It is a good practice to include a text version in addition to the HTML version.
614
601
615
602
616
603
[source,erb]
@@ -691,9 +678,9 @@ $ git merge chapter07
691
678
692
679
== Conclusion
693
680
694
-
That's it! You did it! You can applaud yourself. I know it's been a long time, but it's almost over, believe me.
681
+
That's it! You did it! You can applaud yourself. I know it's been a long time but believe me it's almost over.
695
682
696
-
In next chapters, we will continue working on the order template to add validations when placing an order. Some scenarios are:
683
+
In next chapters we will continue working on the order template to add validations when placing an order. Some scenarios are:
697
684
698
685
* What happens when products are not available?
699
686
* Decrease the quantity of the product in progress when placing an order
0 commit comments