Skip to main content

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.

resource

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/URICRUD OperationTypical
Controller Action
Has Data
Payload
Possible HTTP Status Codes
GET/postsRead all postsindexNo200, 500
GET/posts/:idRead a specific postshowNo200, 404, 500
POST/postsCreate a new postcreateYes201, 400, 500
PUT/posts/:idUpdate specified postupdateYes200, 400, 404, 500
DELETE/posts/:idDelete specified postdeleteNo204, 404, 500

Additional Common Non-RESTful (CRUD-less) Routes

HTTP Method
(Verb)
Path/Endpoint/URIPurposeTypical
Controller Action
Has Data
Payload
GET/posts/newReturn view (form) to add a new postnewNo
GET/posts/:id/editReturn view (form) to edit a posteditNo
HTTP Method
(Verb)
Path/Endpoint/URICRUD Operation
or Purpose
Note
GET/posts/:id/commentsRead all comments for a postNo payload
GET/comments/:idRead one comment for a post"Shallow" route / No payload
GET/posts/:id/comments/newn/a (Non-RESTful)OPTIONALLY display a dedicated form used to create a nested resource
POST/posts/:id/commentsCreate a comment for a post (1:M)Needs Payload
PUT/comments/:idUpdate specified comment"Shallow" route / Needs payload
DELETE/comments/:idDelete specified comment"Shallow" route / No payload
POST/posts/:postId/blogs/:blogIdAssociate a post with a blog (M:M)No payload
POST/posts/:postId/blogsAssociate a post with a blog (M:M)id of blog included in payload vs endpoint
tip

"Shallow routes are for CRUD operations where the parent's id is not needed. For example, you do not need the id of the post route to delete a specific comment - you only need that particular comment's id.

note

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 of POST /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 as GET /users/:id/profile would be okay.