[MUSIC]
In the previous exercise we have got our loopback servers up to a certain stage.
We are able to now connect our loopback servers to the mongolab database,
the database acting as the data source for our loopback servers.
We also define access controlled lists to control access to the radius,
rest are here, in parts with our loopback server.
In this exercise, we will explore loopback relations.
We can now define models and define relationships between the models.
So, for example, let's take the example of a comment.
When you post a comment about a dish, the comment is related to the dish.
A comment belongs to a dish.
Similarly, a comment is posted by a specific user.
So the comment has belongs to the relationship with this specific user.
Now, when you look at the relationship in the reverse direction,
a dish may have multiple comments associated with it, and
similarly, a user may have posted multiple comments.
So these are the biggest kinds of relationships that you can define between
the various models within our loopback server.
Also we will look at the use of a mixed-in loopback,
which allows us to add additional properties to our models.
At the end of this exercise you will have a pretty much complete loopback server,
which we can then connect to our angular client and
be able to make use of it as the back-end for our angular client.
To continue with the exercise, in our loopback server's folder,
let's create a new model for a comment.
So this model will define as
comment, and in this case that model is also saved
in MongoDB and will be as a persistent model,
and we will expose the comment via the REST API and
the model folder is in the common folder and for
this comment we will have two properties associated with it.
And the first property is Rating.
Which is of the type Number.
This is required and the default value, I will leave that as 5.
And the second property would be Comment, which is of the type string.
This is required and the default value is empty.
So each comment will have these two properties, rating and comment,
associated with it.
Also, we need to now define the relationship between the comment and
the user that is submitting the comment, and also the comment and
the dish with which this comment is associated.
Similarly, we have seen in the earlier exercise that they have added
their favorites for a user.
So to define the favorites, let me again define a model,
and that model name is Favorite and this is also saved in the MongoDB,
and this is also a PersistedModel, and
we will expose the favorite for the rest API and is in the common folder.
Now the favorite itself doesn't need any specific property because all of
the favorite does is associates the specific user with this specific dish.
So the favorite here is going to be used simply as a bridge between the user
and the dish.
So we will use the favorite as a way of defining relations between the dish and
a user.
So it doesn't have any specific properties.
So now we have added two models into our loopback server.
Now, let's start defining the model relations.
Now as I explained earlier,
there are various kinds of model relationships that we can define.
Let's start with defining the relationship between a dish and a comment.
So to define a model in loopback, we'll say, lb relation.
And when the relationship comes in,
we need to specify the model from which to create the relation.
So in the first instance, we will create a relation between a dish.
So from the dishes, and a dish might have many comments associated with it,
so that's why the relation type has many and
is associated with a comment and the property name for the relation
I will leave it as the default with just comment with a small letter c.
Now we can create a specific custom foreign key if we want to.
If we don't, loopback will automatically assign the foreign key,
which would be nothing but the comments and an id associated with it.
So it'll look back to define it automatically.
We can also have through models, which in this case is not applicable.
A through model will allow us to define relation to one and to another model and
in this case, we don't have such relationship, so we'll just say no and
we won't nest the REST API, and also,
we'll disable the relation from being included.
And so, we have specified
that the disabling of the relationship from being included is no.
Later on you will see why this is important.
We would have a way of including information from one
model into another model by doing an include there.
So that is something that we have asked not to be prevented.
Now similarly, we can define the next relationship
between comment and the dishes.
So when you define a relationship to the comment and the dishes, so
let me say it lb relation, and we will now define the relation between the comment.
And since a comment can only belong to a specific dish, so
we'll define it belongs to a relationship, and this is belonging
to the dish here and the property name for the relation would be dishes.
And we will not use a custom foreign key,
we'll allow the relationship to be used in the REST APIs.
Actually we don't want that, so I should have typed in no for that,
but I'll just go and edit the created relation in my code there.
So I can go into the comment.jason file and
just change this from a yes to a no in there,
I'll do that because I don't want it to be nested next.
So let me go ahead and
make that change in the comment called Jason before I forget to do that.
And then open the comment called Jason.
And you see that in the comment called Jason we have this relationship here and
then I am going to cut this out because I don't want that nesting to be done.
That's a mistake that I made while typing in, so I'll delete that.
The next relationship that I'm going to define is between the comment and
the customer.
Let me again, type lb relation here.
So we'll define the relationship between the comment and the customer.
A comment belongs to a customer as we would expect,
and, Here let me explicitly
enter, A custom foreign key.
I'm just doing this to illustrate to you that I can
define a specific foreign key here.
I'll not nest, and I'll not disable here.
So, this is the relationship that I'll define between the comment and
the customer.
Next, Let me define the relationship between the customer and the comment.
So here, from a customer, a customer has many comments,
and their property name I will enter as comments.
And then, I will define the foreign key as customerId.
And I don't require a through model here, I will not nest and I'll not disable.
So now I have defined all of the relationships between the comments and
the customer, and the comments and the dishes.
Now, same thing let's work on the favorites.
Now, for the favorites, Let me define
the relationship between the dishes and the favorites.
So a dish could have been favorites for many users,
so it has many relationship with a favorite.
And we'll use favorites there, and
we'll not need a through model and no and no.
So, now we have defined it has many relationships between the dish and
a favorite.
Let me now define a relationship between a favorite and a dish.
So to define the relationship between the favorite and
the dish let me say favorite belongs to dish, and
we'll use the dishes and no foreign key, not nested.
And we'll not disable the relation from being included.
Now, we'll have to define that relationship between
a favorite and a customer.
So we'll say favorite belongs to a customer and,
We'll define it foreign key as a customerId.
We'll not allow the nesting of the REST API and we'll not disable.
Now the last relationship, Is between the customer and the favorite.
So, now we'll define the relationship between the customer has many,
Favorites, and this,
I'll define the customerId as the foreign key, I don't require a through model,
and I won't allow the nesting and I won't disable anything.
So that's it, we have defined all the relationships that we need
between the comments and the customers and the dishes.
Between the favorites, the customers, and the dishes.
Now, lets examine the use of a mixin.
Now, this mixin that I'm going to use with my Loopback server is
a mixin that adds timestamps to anything that is saved or updated.
So recall that in our Express server, we had the created at and
updated at added automatically by using Mongoose.
Now for Loopback, I need to use this specific
mixin called as Lookback ds timestamp mixin.
so toSdo that I have to first install the mixin into my project.
So I'll say npm install
loopback-ds-timestamp-mixin --save,
and the install this node module.
And once this node module is installed, so as you can see,
this is version number 3.4.1 that I'm using.
As this mixin is installed, I need to go in and
enable this mixin usage within my models.
To do that lets go to the code, in the code let me first open
that model conflict adjacent, which is in the server folder.
So in the model confi.json if you go up here you will see these
mixins defined here.
So we have the mixins from loopback common and loopback server.
Now I'm going to add in the new mixin I have just added here.
So, this mixin is in ../node_modules.
So this is in the node modules folder right there.
/loopback-ds-timestamp-mixin.
This allows my Loopback server to make use of this mixin within my server.
Now not only this, I need to specify for
all the models where I want this mixin to be included.
So, I will go now to that common folder, and
in the common folder we will edit that comment.json file and
in the comment.json file, we will add in the mixin.
So after the properties, I will add in the mixin as
sync within quotes, you'll say mixins.
:, And, there,
and inside the mixins we'll see
TimeStamp, true.
This same thing I need to paste into some of the other models so
let me just copy this.
So we'll say mixins TimeStamp true in comments.json.
Then we will go to dishes.json and
then we'll add this also to dishes.json and
then they will go to favorite.json, and
then add into favorite.json.
We'll add it to readers.json, And
we'll add it to promotions.json.
And save all the changes.
Now we will configure a few more access control list, so
going to the terminal let me type lb acl to configure some access control lists.
So, here for the dishes,
I will specify for all methods and properties the right
Can only be done by the user with the role admin.
So that is the first access control that I configure for
dishes, then I do the same for leaders.
All methods and properties, write, other,
the admin role explicitly grant access.
Then for the promotions also,
the same, all methods and
properties, write, and other,
Role explicitly grant access, because you only want the admin
to be able to make any changes to the dishes, promotions, or leaders.
Now for the comments, the comments can be posted by any registered user.
So for the comments, let me define the ACL for the comments.
We'll say comment, all methods and
properties, all types, all users,
explicitly deny access.
Because we don't want them to be able to do all the things.
Now, let's open only some of the operations to be enabled by users.
So for comments, all methods and
properties, we'll say read operation.
Read operation for the comments will be only an authenticated user.
So only users that are logged in will be able to read the comments.
Now similarly, let me define for the,
Comments, a single method, and
create, who can create comments?
Any authenticated user, any authenticated user can create comments.
So we'll explicitly grant them the access, now,
the last one for comments, We'll say for
the comment, all methods and properties.
Write, meaning that, who is allowed to write the comment?
Only the user owning that object can make changes to the comment.
So only the user that has submitted the comment can make changes to the comment,
either edit or delete the comment, so that's what we will allow.
Same set of operations, let's apply them to the favorites.
So for favorites, since we haven't added
any of the access controls, so for the favorites,
all methods and properties, all types,
all users, explicitly deny access there.
For favorites, we will define for
all methods and properties, read,
only for the user owning that object.
So only the user can read his or
her own favorites, no other user should be able to see his or her own favorites.
Now the third one is creation of favorites,
so for creation of favorites, we will say for
favorite, a single method, create,
any authenticated user can create a comment.
And last, for a favorite, all methods and
properties, the write operation, only for the user owning that object.
So only the user that has input the favorite for himself or
herself can edit or delete those favorites, that's it.
So we have now set up all of the access controls and
all the various relations for our application.
Let's now start the Rest API of the server, and
then explore some of these details.
Now, going to our application in the browser, so
we'll go to that LoopBack Explorer in the browser here.
In the LoopBack Explorer, what I'm going to do first is to log in as the admin.
So we will login as the admin by going to the /Customers/login.
And then here we will type in username,
Admin, Password,
Password, And log ourselves in,
and once we have logged in, I'm just going to copy this ID,
because this is the access token.
And I'm going to go in here, and then set the access token with
this new access token that I have just obtained, after that,
Let me post a few dishes to my server, so
now that I am logged in as an admin,
I should be able to post dishes to my server.
So I'll open post, and recall that I had given you the DB.json file,
so we can just copy and paste the dishes into the data field here.
This is my first dish, and the moment I post,
it will come back with the dish information here.
And note that it automatically adds in the createdAt and updatedAt fields here.
This is my second dish, so finally, I have completed inputting all the dishes,
all the leaders, and all the promotions, and we are all done.
So let's now go ahead and
then register a new customer into the system.
So to do that, let me remove this
access token, and then we'll register a new customer into the system.
So to do that, we will go to post customers, and then for the data,
let me just click on this example value here, and then post it in here.
And for the data, the first name,
let me register myself with my first name.
So this would be a non-admin
user that I am registering, and,
And this email verified I should removed this from here, But I should include the,
password field in here, So that I can register the user.
So I'm registering a new ordinary user in here.
So when I register it comes back to confirm that this new registered
user is added in, and also gives me an ID for that user.
Now let me log in as this registered user and then post a couple of comments.
So to log in as the registered user, I will go down to the customer login,
and for the username, I'll type in my name and
the password and then when I login, it'll come back and give me an ID.
Now note that this particular user is an ordinary user not an admin,
so this user can only post comments and edit his or her own comments.
And or post-favorites and edit his or her own favorites.
So, when you post the user, you will see that it is the userId returned here,
shis is the ID for the user.
So, we would need this whenever we post comments or
whenever we post our favorites.
So, to post a comment for this user, so
to post a comment, let me post a couple of comments on behalf of this user.
So, we'll go to Comments, and then we'll post some comments here.
So, to post a comment as you notice,
we need to supply three pieces of information.
We need to supply the customerId, the dishesId, the rating and the comment.
So for the customerId, we just logged in, so
if you go to the customers and down here at the bottom.
We will get the customerId here, so let me copy the userId from here.
And then go up into the comments posting section and
then paste the customerId in there.
Let me now go and find a dish.
So if you go to, Dishes and then you do a get on the dishes,
you'll get all the dishes that are in the system.
So from this let me select the,
First dish, so I'll just take the ID of the dish.
Then to post the comments, we'll just go to Comments,
Post where we are composing our comment.
And then I'll paste the dish's ID in there.
And for the rating, I will change this rating to 4 and,
Just post, This comment,
so I've posted one comment for this particular dish.
Let me post one more comment for another dish.
So let me get hold of this second dish.
So here's the ID of the second dish so, again, going back to Comments.
Let me change the dishId here.
And then, Let me change the comments so
that you see that this is a different comment for a different dish.
When I post the comment, you would see that it'll come back with this reply here,
with the rating and the specific dish and the customerId and so on.
So I have now posted two comments for two different dishes here.
Let me, Make these two as my favorite dishes.
So to do that, let me go to Favorites.
Going down to favorites.
Let me post a couple of favorites.
So to post a favorite again, I go into the post favorites here.
Then I click on this and then I'll paste in the one dishId,
for the customerId, let me just go up to the customer here,
where I logged in the customer.
So we'll get the userId from there.
And this is one customerId, so let me go to the Favorites.
And then, In the Favorites
let me test the customerId here, and then post this into my favorites.
So when I post that into my favorites it replies back with this so
you can see that the dishId and customerId and the favoriteId have been posted here.
Let me post one more dish to my favorites so let me go to the,
Dishes here I have another dish.
So let me copy the, ID of the dish and go to my favorites and
then replace the dishe's ID with that new dish, and then post that.
So now I should have two favorites in my group.
Wonderful, so now we have a couple of favorites,
a bunch of dishes, a couple of comments, all posted in.
Now how is this useful?
Let me, Close all this and then will show you how this can be useful.
So, now when I do get dishes, so for example,
when I want to forget a specific dish.
Let me get this first dish here, let me copy the ID of the dish and,
I can retrieve that specific dish.
So here you see that I'm going to /dishes/Id so
here, when I want to retrieve that specific dish.
I can put the dishId there and then try it out and
then here I get the dishId here.
Now, if I want to include the comments from the dish, then in the filter,
I should type in include in quotes and
then within brackets I specify,
The name of,
The relation that I want to include into that,
so when I say include comments.
So this is like the Mongols populate, it acts similarly.
So when I say include comments and then retrieve the dish,
notice that when the dish is retrieved,
Here, you get the dish but also you get an array Of comments here.
So that is how you can fill in the details from the relation
that you have with another element here.
Now, similarly, going to comments, for example.
In the comments also, when I retrieve the comments, I can specify within the filter.
So when I just say GET comments, it'll bring
back all the comments that have been posted.
Now, if I want to fill in the dishId and customerId information, I can say filter.
In the filter, I can say include.
And then within brackets, I can say dishes because
that's the relationship that I have defined within the comments and
the dishes, and then dishes and customer.
And when I retrieve this information, you will see that in the returned comments,
for each comment, you will notice that the comment is given and
then the corresponding dish information is also filled in, and
the corresponding customer information is also filled in for each of the comment.
So that way, we can now populate the two relationships that we have defined from
the dishes automatically in here, as shown here.
Similarly, for the favorites,
when we are retrieving the favorites,
we'll say favorites and a specific ID here.
And then we can then filter, so
that specific favorite can be retrieved.
You can't retrieve all the favorites because they could be favorites from other
users also in that list, so we won't be able to do a GET on all the favorites.
But instead, when we retrieve this, you can then ask for
the information to be filled in here based on the relationships.
So we can say, in quote, ("include": and written square brackets.
We can say ["dishes", "customer"]),
And retrieve the information.
So you would notice that here, in the Response Body,
you get the favorite, but also the corresponding dish and
the corresponding customer's information filled in here.
So that's how we can retrieve additional information
from our server site as required.
With this, we complete this exercise.
In this exercise, I have demonstrated to you how we can define various relations
and then be able to retrieve information, and also use this include
filter in order to include the additional information of that relationship into
the document when you retrieve the document or a set of documents.
With this, we complete this exercise.
So in these three exercises that we have done so far with LoopBack, I have
illustrated various aspects of how you can configure and build your LoopBack server.
With this, we complete this exercise.
This is a good time for
you to do a GET comment with the message LoopBack relations.
[MUSIC]