Add Operation Hooks to a LoopBack model

Bram Borggreve
InstructorBram Borggreve

Share this video with your friends

Send Tweet
Published 5 years ago
Updated 3 years ago

In this lesson we will learn how to add operation hooks to our models. In the Product model we will create a before safe observer that will check if the category we want to add the product to exists.

In our Category model we will create a before delete observer to prevent categories from being deleted when they have products.

We will create a unit test to verify that both of these operation hooks work as expected.

[00:00] Inside our product model class, we will add a new static method called product.observe. As a first parameter, we pass in what we want to observe, in this case, before save.

[00:09] Second parameter is a callback method which takes two parameters, CTX, which stands for context, and next, which is the callback. Inside our method, we create an if statement where we check if we receive an instance on the context, and that this instance has a category ID.

[00:25] We load the if statement, so when our condition is not true, we return next so LoopBack can continue its work. Inside our if statement, we will check if the category where we want to add the product to exists.

[00:37] We do this by getting a reference to the category model through our product model. On the category model, we run the count methods, and as a parameter, we pass in that we want the counts, the categories that have an ID matching to our requested category ID.

[00:51] The count method returns a promise with the number of items. In the then block, we check if the number is lower than one. If so, we return a promise.reject with an error message.

[01:02] In our product test, we will add a new section where we'll test our hooks. In here, we create our test. We will try to create a new product, and as a category ID, we pass in an ID that does not exist.

[01:14] In the catch block, we verify that the error message is what we expect. When we run our test, we see that our new test passes.

[01:21] In our category model, we will add a before delete observer. Callback only takes the context, because we will directly return a promise.

[01:30] Inside our method, we get a reference to our product model through our category model. On the product model, we run counts, and as the parameter, we pass in that we want the counts to products that have a category ID matching with the one in our context.

[01:44] In the then block, we check if the number of products is higher than one, and if so, we return promise.reject with an error message. We create the file category.test.js in our test/unit folder, and we require app and expect from our common file.

[02:00] Next, we create a reference to the category and the product models. We add a describe block for category, and inside that describe block, we add a block for the hooks.

[02:09] In our test, we start the promise chain with a promise.resolve. We create a category called my category, and we get the results in the second then block.

[02:18] We will use the ID of the results to create our new products, so after product.create run, we have a category with one product.

[02:25] In the third then block, we use category.destroybyID to delete the category, and in our catch block, we verify that we get the error we expect. If we save our file and run our test, we see that the category test passes.

Victor Hazbun
Victor Hazbun
~ 5 years ago

why the product hook returns next() and the category model does not?

Frederic Rey
Frederic Rey
~ 4 years ago

Hello! It seems we can do the same with an Async Validator, is there an advantage using a Hook over it ? What I can see is:

  • With a Validator, only the current Model Instance is available, unless the Model itself is in a parent scope (which is the case) or injected
  • With a Hook, at least the current Model instance and every Model are available