justatester
justatester

Reputation: 391

Customize loopback model

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

Upvotes: 1

Views: 301

Answers (3)

justatester
justatester

Reputation: 391

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.

Upvotes: 0

harish1792
harish1792

Reputation: 11

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

Upvotes: 0

Karan Raina
Karan Raina

Reputation: 600

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
           }

        }
    }
}

Upvotes: 0

Related Questions