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: en/00_before.adoc
+2-2Lines changed: 2 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -2,7 +2,7 @@
2
2
3
3
"API on Rails 5" is based on http://apionrails.icalialabs.com/book/["APIs on Rails: Building REST APIs with Rails"]. It was initially published in 2014 by https://twitter.com/kurenn[Abraham Kuri] under the licenses http://opensource.org/licenses/MIT[MIT] and http://people.freebsd.org/~phk/[Beerware].
4
4
5
-
Since the original work was not maintained, I wanted to update this excellent work and contribute to the Francophone community by translating it myself. This update is also available in the Molière languagefootnote:[It means french.].
5
+
Since the original work was not maintained, I wanted to update this excellent work and contribute to the Francophone community by translating it myself. This update is also available in the Molière language footnote:[It means french.].
6
6
7
7
== About the author
8
8
@@ -20,7 +20,7 @@ This book is provided on http://opensource.org/licenses/MIT[MIT license]. All th
20
20
****
21
21
Copyright 2019 Alexandre Rousseau
22
22
23
-
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ``Software''), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
23
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
24
24
25
25
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
Copy file name to clipboardExpand all lines: en/01_introduction.adoc
+11-13Lines changed: 11 additions & 13 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -138,7 +138,7 @@ $ rails -v 5.2
138
138
5.2.0
139
139
----
140
140
141
-
===== Bases de données
141
+
===== Database
142
142
143
143
I highly recommend you install http://www.postgresql.org/[Postgresql] to manage your databases, but for simplicity we’ll be using http://www.sqlite.org/[SQlite]. If you are using Mac OS you should be ready to go, in case you are on Linux, don’t worry we have you covered:
Initializing a Rails application must be pretty straightforward for you, if that is not the case, here is a super quick tutorial.
160
160
161
-
Be aware that we’ll be using http://rspec.info/[Rspec] as the testing suite. So we will use the donc `--skip-test` option. Also we will use `--api` option.
161
+
Be aware that we’ll be using http://rspec.info/[Rspec] as the testing suite. So we will use the `--skip-test` option. Also we will use `--api` option.
162
162
163
163
NOTE: This option came with Rails 5 and it allow to limit gems and Middleware. It will also avoid to generate HTML views when using Rails generators.
164
164
@@ -183,7 +183,9 @@ and the answer is simple, we will be working with http://en.wikipedia.org/wiki/S
183
183
184
184
===== Installing Pow
185
185
186
-
Pow only works on Mac OS, but don’t worry there is an alternative which mimics the functionality on Linux. To install it just type in:
186
+
NOTE: Pow only works on Mac OS, but don’t worry there is an alternative which mimics the functionality on Linux.
187
+
188
+
To install it just type in:
187
189
188
190
[source,bash]
189
191
----
@@ -208,7 +210,7 @@ Remember to change the user directory to the one matches yours. You can now acce
208
210
209
211
===== Installing Prax
210
212
211
-
For linux users only, https://github.com/ysbaddaden/prax.cr[Prax] distribute some Debian/Ubuntu precompiled packages. You only have to download `.deb` eand instal with `dpkg`.
213
+
For linux users only, https://github.com/ysbaddaden/prax.cr[Prax] distribute some Debian/Ubuntu precompiled packages. You only have to download `.deb` and instal with `dpkg`.
212
214
213
215
[source,bash]
214
216
----
@@ -225,7 +227,7 @@ $ cd ~/workspace/market_place_api
225
227
$ prax link
226
228
----
227
229
228
-
If you want to start the prax server automatically, add this line to the `.profile` file:
230
+
If you want to start the Prax server automatically, add this line to the `.profile` file:
229
231
230
232
....
231
233
prax start
@@ -237,7 +239,7 @@ You should see the application up and running, see image bellow:
237
239
238
240
=== Gemfile and Bundler
239
241
240
-
Once the Rails application is created, the next step is adding a simple but very powerful gem to serialize the resources we are going to expose on the api. The gem is called `active_model_serializers` which is an excellent choice to go when building this type of application, is well maintained and the https://github.com/rails-api/active_model_serializers[documentation] is amazing.
242
+
Once the Rails application is created, the next step is adding a simple but very powerful gem to serialize the resources we are going to expose on the api. The gem is called `active_model_serializers` which is an excellent choice to go when building this type of application. It is well maintained and the https://github.com/rails-api/active_model_serializers[documentation] is amazing.
241
243
242
244
So your `Gemfile` should look like this after adding the `active _model_serializers` gem:
Notice that I remove the `jbuilder` and `turbolinks` gems, as we are not really going to use them anyway.
270
+
NOTE: I remove the `jbuilder` and `turbolinks` gems because we are not really going to use them anyway.
269
271
270
272
It is a good practice also to include the ruby version used on the whole project, this prevents dependencies to break if the code is shared among different developers, whether if is a private or public project.
271
273
@@ -296,11 +298,9 @@ $ bundle install
296
298
297
299
After the command finish its execution, it is time to start tracking the project with Git.
298
300
299
-
=== Versionning
300
-
301
-
Remember that Git helps you track and maintain history of your code. Keep in mind source code of the application is published on Github. You can follow the repository at [Github][api_on_rails_git]
301
+
=== Versioning
302
302
303
-
I’ll assume you have git already configured and ready to use to start tracking the project. If that is not your case, follow these first-time setup steps:
303
+
Remember that Git helps you track and maintain history of your code. Keep in mind source code of the application is published on Github. You can follow the repository at https://github.com/madeindjs/api_on_rails[Github]. I’ll assume you have Git already configured and ready to use to start tracking the project. If that is not your case, follow these first-time setup steps:
304
304
305
305
[source,bash]
306
306
----
@@ -313,8 +313,6 @@ NOTE: Replace the last command editor(`"mvim -f"`) with the one you installed `"
313
313
314
314
So it is now time to *init* the project with git. Remember to navigate to the root directory of the `market_place_api` application:
315
315
316
-
So it is now time to *init* the project with git. Remember to navigate to the root directory of the `market_place_api` application:
Copy file name to clipboardExpand all lines: en/02_api.adoc
+22-15Lines changed: 22 additions & 15 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -15,23 +15,25 @@ And as a quick recap, we really just update the `Gemfile` to add the `active_mod
15
15
16
16
=== Planning the application
17
17
18
-
As we want to go simple with the application, it consists on 5 models. Don’t worry if you don’t fully understand what is going on, we will review and build each of these resources as we move on with the tutorial.
18
+
As we want to go simple with the application, it consists on five models. Don’t worry if you don’t fully understand what is going on, we will review and build each of these resources as we move on with the tutorial.
19
19
20
20
image:data_model.png[Schema of links betweens models]
21
21
22
22
In short terms we have the `user` who will be able to place many `orders`, upload multiple `products` which can have many `images` or `comments` from another users on the app.
23
23
24
24
We are not going to build views for displaying or interacting with the API, so not to make this a huge tutorial, I’ll let that to you. There are plenty of options out there, from javascript frameworks(https://angularjs.org/[Angular], http://emberjs.com/[EmberJS], http://backbonejs.org/[Backbone]) to mobile consumption(https://github.com/AFNetworking/AFNetworking[AFNetworking]).
25
25
26
-
By this point you must be asking yourself, all right but I need to explore or visualize the api we are going to be building, and that’s fair. Probably if you google something related to api exploring, an application called https://chrome.google.com/webstore/detail/postman-rest-client/fdmmgilgnpjigdojojpjoooidkmcomcm?hl=en[Postman] will pop, it is a great add on if you are using chrome, but we won’t be using that anyway, as probably not every developer uses the Google browser.
26
+
By this point you must be asking yourself, all right but I need to explore or visualize the api we are going to be building, and that’s fair. Probably if you google something related to api exploring, an application called https://www.getpostman.com/[Postman] will pop. It is a great software but we won’t be using that anyway because we'll use cURL who allow anybody to reproduce request on any computer.
27
27
28
28
=== Setting the API
29
29
30
-
An API is defined by http://en.wikipedia.org/wiki/Application_programming_interface[wikipedia] as _an application programming interface (API) specifies how some software components should interact with each other._ In other words the way systems interact with each other through a common interface, in our case a web service built with `json`. There are other kinds of communication protocols like SOAP, but we are not covering that in here.
30
+
An API is defined by http://en.wikipedia.org/wiki/Application_programming_interface[wikipedia] as _an application programming interface (API) specifies how some software components should interact with each other._ In other words the way systems interact with each other through a common interface, in our case a web service built with JSON. There are other kinds of communication protocols like SOAP, but we are not covering that in here.
31
31
32
32
JSON as the Internet media type is highly accepted because of readability, extensibility and easy to implement in fact many of the current frameworks consume JSON api’s by default, in Javascript there is https://angularjs.org/[Angular] or http://emberjs.com/[EmberJS], but there are great libraries for objective-c too like https://github.com/AFNetworking/AFNetworking[AFNetworking] or http://restkit.org/[RESTKit]. There are probably good solutions for Android, but because of my lack of experience on that development platform I might not be the right person to recommend you something.
33
33
34
-
All right, so we are building our api with `json`, but there are many ways to achieve this, the first thing that could come to your mind would be just to start dropping some routes defining the http://en.wikipedia.org/wiki/Web_Services_Description_Language#Objects_in_WSDL_1.1_.2F_WSDL_2.0[end points] but they may not have a http://www.w3.org/2005/Incubator/wcl/matching.html[URI pattern] clear enough to know which resource is being exposed. The protocol or structure I’m talking about is http://en.wikipedia.org/wiki/Representational_state_transfer[REST] which stands for Representational State Transfer and by wikipedia definition _is a way to create, read, update or delete information on a server using simple HTTP calls. It is an alternative to more complex mechanisms like SOAP, CORBA and RPC. A REST call is simply a GET HTTP request to the server._
34
+
All right, so we are building our API with JSON, but there are many ways to achieve this, the first thing that could come to your mind would be just to start dropping some routes defining the http://en.wikipedia.org/wiki/Web_Services_Description_Language#Objects_in_WSDL_1.1_.2F_WSDL_2.0[end points] but they may not have a http://www.w3.org/2005/Incubator/wcl/matching.html[URI pattern] clear enough to know which resource is being exposed. The protocol or structure I’m talking about is http://en.wikipedia.org/wiki/Representational_state_transfer[REST] which stands for Representational State Transfer and by wikipedia definition
35
+
36
+
> is a way to create, read, update or delete information on a server using simple HTTP calls. It is an alternative to more complex mechanisms like SOAP, CORBA and RPC. A REST call is simply a GET HTTP request to the server.
35
37
36
38
[source,soap]
37
39
----
@@ -40,10 +42,10 @@ aService.getUser("1")
40
42
41
43
And in REST you may call a URL with an e specific HTTP request, in this case with a GET request: ~~~ http://domain.com/resources_name/uri_pattern ~~~
42
44
43
-
RESTful APIs must follow at least 3 simple guidelines:
45
+
RESTful APIs must follow at least three simple guidelines:
44
46
45
47
* A base http://en.wikipedia.org/wiki/Uniform_resource_identifier[URI], such as `http://example.com/resources/`.
46
-
* An Internet media type to represent the data, it is commonly `JSON` and is commonly set through headers exchange.
48
+
* An Internet media type to represent the data, it is commonly JSON and is commonly set through headers exchange.
47
49
* Follow the standard http://en.wikipedia.org/wiki/HTTP_method#Request_methods[HTTP Methods] such as GET, POST, PUT, DELETE.
48
50
** *GET*: Reads the resource or resources defined by the URI pattern
49
51
** *POST*: Creates a new entry into the resources collection
@@ -102,6 +104,8 @@ end
102
104
103
105
By defining a namespace under the `routes.rb` file. Rails will automatically map that namespace to a directory matching the name under the `controllers` folder, in our case the `api/` directory.
104
106
107
+
.Rails media types supported
108
+
****
105
109
Rails can handle up to 35 different media types, you can list them by accessing the SET class under de Mime module:
106
110
107
111
[source,bash]
@@ -111,6 +115,7 @@ Loading development environment (Rails 5.2.1)
This is important because we are going to be working with JSON, one of the built-in http://en.wikipedia.org/wiki/Internet_media_type[MIME types] accepted by Rails, so we just need to specify this format as the default one:
116
121
@@ -125,7 +130,7 @@ Rails.application.routes.draw do
125
130
end
126
131
----
127
132
128
-
Up to this point we have not made anything crazy, what we want to achieve next is how to generate a _base_uri_ under a subdomain, in our case something like `api.market_place_api.dev`. Setting the api under a subdomain is a good practice because it allows to scale the application to a DNS level. So how do we achieve that?
133
+
Up to this point we have not made anything crazy. What we want to to generate a _base_uri_ under a subdomain. In our case something like `api.market_place_api.dev`. Setting the api under a subdomain is a good practice because it allows to scale the application to a DNS level. So how do we achieve that?
129
134
130
135
[source,ruby]
131
136
.config/routes.rb
@@ -138,17 +143,20 @@ Rails.application.routes.draw do
138
143
end
139
144
----
140
145
141
-
Notice the changes?, we didn’t just add a `constraints` hash to specify the subdomain, but we also add the `path` option, and set it a _backslash_. This is telling Rails to set the starting path for each request to be root in relation to the subdomain, achieving what we are looking for.
142
-
143
-
==== Common api patterns
146
+
Notice the changes? We didn’t just add an https://ruby-doc.org/core-2.4.0/Hash.html[`Hash`] constraints to specify the subdomain. We also add the `path` option, and set it on root path (`/`). This is telling Rails to set the starting path for each request to be root in relation to the subdomain, achieving what we are looking for.
144
147
148
+
.Common API patterns
149
+
****
145
150
You can find many approaches to set up the _base_uri_ when building an api following different patterns, assuming we are versioning our api:
146
151
147
152
* `api.example.com/`: I my opinion this is the way to go, gives you a better interface and isolation, and in the long term can help you to http://www.makeuseof.com/tag/optimize-your-dns-for-faster-internet/[quickly scalate]
148
153
* `example.com/api/`: This pattern is very common, and it is actually a good way to go when you don’t want to namespace your api under a subdomain
149
154
* `example.com/api/v1`: his seems like a good idea, by setting the version of the api through the URL seems like a more descriptive pattern, but this way you enforce the version to be included on URL on each request, so if you ever decide to change this pattern, this becomes a problem of maintenance in the long-term
150
155
151
-
Don’t worry about versioning right now, I’ll walk through it later. Time to commit:
156
+
Don’t worry about versioning right now, I’ll walk through it later.
157
+
****
158
+
159
+
Time to commit:
152
160
153
161
[source,bash]
154
162
----
@@ -210,7 +218,7 @@ Well first of all, we need to improve the API version access through http://en.w
210
218
211
219
.Most commons HTTP headers fields
212
220
****
213
-
HTTP header fields are components of the message header of requests and responses in the Hypertext Transfer Protocol (HTTP). They define operating parameters of an HTTP transaction. A common list of used headers is presented below:
221
+
HTTP header fields are components of the message header of requests and responses in the Hypertext Transfer Protocol (HTTP). They define an operating parameters of an HTTP transaction. A common list of used headers is presented below:
214
222
215
223
* *Accept*: Content-Types that are acceptable for the response. Example: `Accept: text/plain`
Let me walk you through the code. We are initializing the class with an options hash, which will contain the version of the api, and a default value for handling the default version. We provide a `matches?` method which the router will trigger for the constraint to see if the default version is required or the `Accept` header matches the given string.
323
+
Let me walk you through the code. We are initializing the class with an https://ruby-doc.org/core-2.4.0/Hash.html[`Hash`] option. https://ruby-doc.org/core-2.4.0/Hash.html[`Hash`] option will contain the version of the API and a default value for handling the default version. We provide a `matches?` method which the router will trigger for the constraint to see if the default version is required or the `Accept` header matches the given string.
316
324
317
325
The implementation looks likes this
318
326
@@ -336,8 +344,7 @@ As you imagine we need to add the class to our `routes.rb` file and set it as a
0 commit comments