1

How do i customize a PersistedModel in loopback ? Let's say i have two models Post and Comment. A Post hasMany Comment but it can have at most 3 comments. How can i implement that without using hooks? Also i need to do it inside a transaction.

I'm coming from java and this is how i would do that:

class Post  {

   void addComment(Comment c) {

         if(this.comments.size() < 3)
              this.comments.add(c) 
         else 
           throw new DomainException("Comment count exceeded") 

   }

 }

then i would write a service ...

  class PostService {

      @Transactional
      public void addCommentToPost(postId, Comment comment) {
             post = this.postRepository.findById(postId); 
             post.addComment(comment)
             this.postRepository.save(post); 

      }

  }

I know i could write something like:

module.exports = function(app) {

      app.datasources.myds.transaction(async (models) => {

         post = await models.Post.findById(postId) 
         post.comments.create(commentData); ???? how do i restrict comments array size ? 




      })


}

i want to be able to use it like this:

// create post 

POST /post --> HTTP 201

// add comments 

POST /post/id/comments --> HTTP 201
POST /post/id/comments --> HTTP 201
POST /post/id/comments --> HTTP 201

// should fail 

POST /post/id/comments --> HTTP 4XX ERROR
justatester
  • 391
  • 3
  • 11

3 Answers3

0

What you are asking here is actually one of the good use cases of using operation hooks, beforesave() in particatular. See more about it here here https://loopback.io/doc/en/lb3/Operation-hooks.html#before-save

However, I'm not so sure about the transaction part.

For that, I'd suggest using a remote method, it gives you complete freedom to use the transaction APIs of loopback. One thing to consider here is that you'll have to make sure that all comments are created through your method only and not through default loopback methods.

You can then do something like this

// in post-comment.js model file    

module.exports = function(Postcomment){

    Postcomment.addComments = function(data, callback) {
        // assuming data is an object which gives you the postId and commentsArray
        const { comments, postId } = data;

        Postcomment.count({ where: { postId } }, (err1, count) => {
          if (count + commentsArray.length <= 10) {
             // initiate transaction api and make a create call to db and callback

           } else {

             // return an error message in callback
           }

        }
    }
}
Karan Raina
  • 560
  • 4
  • 15
  • you said it can be done with a beforesave hook. how would you do that ? – justatester Jun 09 '18 at 20:13
  • In the before save hook, you'll have to query your model like in the answer above, check if the sum of existing comments and new comments is not more than what you want and then invoke the transaction api and create new comments. – Karan Raina Jun 13 '18 at 07:34
0

You can use validateLengthOf() method available for each model as part of the validatable class. For more details refer to Loopback Validation

harish1792
  • 11
  • 3
0

i think i have found a solution. whenever you want to override methods created by model relations, write a boot script like this:

module.exports = function(app) {

    const old = app.models.Post.prototype.__create__comments;
    Post.prototype.__create__orders = function() {
      // **custom code**
       old.apply(this, arguments);
    };

};

i think this is the best choice.

justatester
  • 391
  • 3
  • 11