RESTful Routes to CRUD Mapping
URI Patterns
We want to build maintainable, scalable applications.
To do that, we want to have a plan on how we name our URLs.
Let's say we want to make an app that tracks bookmarks for us.
We want to be able to
- Create a bookmark
- See a list of our bookmarks
- See the details of one bookmark
- Update a bookmark
- Delete a bookmark
Let's take ~5 minutes to answer: How should we organize our URLs?
Good URIs shouldn't change
When you provide a link, it should always work.
Some URI Pain points
- version 2.0, reorganization to make the app better (while the app should improve, the URIs should be able to stay constant, if they were designed well)
- confidential/valid/up to date/out of date - how to organize?
- moving files - you should be able to move files without changing the URI
- making the name too specific/have too many details ie putting
/jane
in the URL because she worked on it. Then John takes over part of Jane's work. Yikes.
Describe REST and list the various routes
Lucky for us, some brilliant minds have developed a URI pattern that solves a lot of the above problems. If we follow the pattern, we can alleviate a lot of pain points.
- REST stands for Representational state transfer
- It's just a set of principles that describe how networked resources are accessed and manipulated
- We have 5 + 2 RESTful routes that allow us basic operations for reading and manipulating a collection of data:
Example resource: posts
HTTP Method (Verb) | Path/Endpoint/URI | CRUD Operation | Typical Controller Action | Has Data Payload | Possible HTTP Status Codes |
---|---|---|---|---|---|
GET | /posts | Read all posts | index | No | 200, 500 |
GET | /posts/:id | Read a specific post | show | No | 200, 404, 500 |
POST | /posts | Create a new post | create | Yes | 201, 400, 500 |
PUT | /posts/:id | Update specified post | update | Yes | 200, 400, 404, 500 |
DELETE | /posts/:id | Delete specified post | delete | No | 204, 404, 500 |
Additional Common Non-RESTful (CRUD-less) Routes
HTTP Method (Verb) | Path/Endpoint/URI | Purpose | Typical Controller Action | Has Data Payload |
---|---|---|---|---|
GET | /posts/new | Return view (form) to add a new post | new | No |
GET | /posts/:id/edit | Return view (form) to edit a post | edit | No |
Routing for Related Resources (One:Many & Many:Many Relationships)
HTTP Method (Verb) | Path/Endpoint/URI | CRUD Operation or Purpose | Note |
---|---|---|---|
GET | /posts/:id/comments | Read all comments for a post | No payload |
GET | /comments/:id | Read one comment for a post | "Shallow" route / No payload |
GET | /posts/:id/comments/new | n/a (Non-RESTful) | OPTIONALLY display a dedicated form used to create a nested resource |
POST | /posts/:id/comments | Create a comment for a post (1:M) | Needs Payload |
PUT | /comments/:id | Update specified comment | "Shallow" route / Needs payload |
DELETE | /comments/:id | Delete specified comment | "Shallow" route / No payload |
POST | /posts/:postId/blogs/:blogId | Associate a post with a blog (M:M) | No payload |
POST | /posts/:postId/blogs | Associate a post with a blog (M:M) | id of blog included in payload vs endpoint |
"Shallow routes are for CRUD operations where the parent's
id
is not needed. For example, you do not need theid
of the post route to delete a specific comment - you only need that particular comment'sid
.
Most apps have data resources related to the logged in user. However, in regards to routing, DO NOT treat these data resources as nested resources. The server will already know who the logged in user is, therefore you will never need to, nor should you, provide the id of the logged in user, for example, never have a route such as
POST /users/:id/posts
. Instead, a route ofPOST /posts
is sufficient for creating a post for the logged in user. This being the case, if for some reason your app's functionality calls for reading a paricular user's data that is not the logged in user, then yes, a route such asGET /users/:id/profile
would be okay.