API Design in Node.js, v5

Get All Habits Controller

Scott Moss
Netflix
API Design in Node.js, v5

Lesson Description

The "Get All Habits Controller" Lesson is part of the full, API Design in Node.js, v5 course featured in this preview video. Here's what you'd learn in this lesson:

Scott creates a getUserHabits function to retrieve all habits for a user, joining tables and transforming data in JavaScript to include tags. He also notes that transformations are usually done in the database for efficiency, and that GET requests do not require input validation.

Preview
Close

Transcript from the "Get All Habits Controller" Lesson

[00:00:00]
>> Speaker 1: All right, let's go back to our controller So we have that Now let's create one where you can get all the habits for a user go back here, collapse this We'll say export const get user habits, so give me all the habits for this user Now I'm going to have this request, which is going to be an authenticated request and a response, which is a response

[00:00:00]
Do I try-catch And what I want to do here is say user habits with tags So if there are any tags associated with this, even though I don't have a way outside of REST or I didn't invent a query language to allow you to tell me if you want me to get the tags for you or not, I'm just going to get the tags for you if there are any tags to get, so you don't have to tell me

[00:00:00]
I'll just say DB query habits dot find many And then I can do it where the habits table user ID field is equal to req.user.id But I also want to get any associated habits with this, so I'm going to do a with clause With allows me to join a table so I can say with habitats And then on that table there is a tag, so I can say with tag and then I can say true

[00:00:00]
It's essentially equivalent to doing a join I was going to say left join, but I don't think that's right for a many-to-many table I don't know the SQL way of describing that, but we're just joining them We're basically starting on the habits table side which has a relationship to the habit tags table which also has a relationship to the tags table

[00:00:00]
The only way to figure out what tags a habit has is to go through that intermediary table that we created called habit tags, and that's what I'm doing So I'm saying find all the habits and then find all the habitats for that habit, and then if you find any, grab all the tags for those habit tags Complicated, yes The true tag calling true means include this field

[00:00:00]
Oh, because you don't want the other relationship IDs or you just want the tag I just want that one Because on the habit tag there's also a recursive relationship, there's also a habit I'll put true on the habit tag that would be on this habit tag would be the same habit that is top level here, so that would be recursive User with habitats and then lastly, we can do an order by, so we want to order by in a descending order, that's what this is

[00:00:00]
We can just order by when they were created, so habits created at in a descending order Which means the newest ones will be at the top Because this is just like spaghetti, we can write a transform function Ideally, you would do this on the database level But I don't have time for that, so we're going to do it in JavaScript What we want to do is transform the output of this to make it look cleaner because right now the table in the middle is kind of gross and it makes the object weird to work with

[00:00:00]
So we want to merge them together essentially, make it more flat—we want to flatten it I'm going to say habits with tags equals user habit tags map For each one of these habits, what we want to do is create a new object, and we want to get the whole habit And then we want to create a new property on this object called tags because right now we don't have that

[00:00:00]
We have something called habit tags, and each one of those will have a tag I just want the tags Just give me an array of tags I'm going to say tags is going to be whatever this habit.habit tags is mapped over Get the habit tag and then I want to return the habit tag tag So now I have an array of tags Just to make sure there is no habit tag ever on here, I'm just going to set that to undefined, which when you send something undefined over the wire, it gets excluded when you JSON stringify or find anything undefined

[00:00:00]
This essentially removes this field from this object This habit right here has a field on it called habit tags here This is us removing it If you can find a way to do this on your database with like a materialized view or some type of transform or even just a better query using a select, that's probably what you want to do But I'm not a SQL wizard, so I'm not doing that

[00:00:00]
Res.json You can just send back the habits Just like this: habits with tags And just like before, if there's an error, we'll just copy what we had here So if there's an error, we can just say get habits error, and then we could just say failed to fetch habits If we go back to our habit routes, that's going to be for getting all the habits for a user, so that would be Router.get slash

[00:00:00]
There's no ID here, so that means give me all the habits I will get rid of this and I would just say get habits, user habits There's no input validation here because you don't send anything up Get request has no payload, so we don't have to validate any input because there is no input Inputs are only for put, post, and patch, not get There could be validation on get because we do allow our server to validate query parameters, and you can definitely add query parameters on get, but we're not using query parameters here

[00:00:00]
If I were to use query parameters here, I would create my own query language and say you can add a query parameter that says tags true, and if I see tags true, then I'll do this But again, you're just making your own stuff at that point.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now