James Clare
James Clare

Reputation: 563

Include Loopback relation in POST response

I have a working chat-room loopback project, which also utilises Socket.IO.

Once I create a Message (POST to Loopback REST API), I need the response the include the 'creator' relation.

This works fine when using GET, but I cannot include the relation to the POST response.

I'm sure it's a simple remote hook, but I'm stuck...

Any help is greatly appreciated!

"relations": {
  "creator": {
    "type": "belongsTo",
    "model": "Person",
    "foreignKey": "",
    "options": {
      "nestRemoting": true
    }
  },
  "event": {
    "type": "belongsTo",
    "model": "Event",
    "foreignKey": "",
    "options": {
      "nestRemoting": true
    }
  }
},

Upvotes: 2

Views: 418

Answers (1)

Peter Liapin
Peter Liapin

Reputation: 1275

There are two options how you can do it with Loopback 2.x or 3.x (not sure about the Loopback 4.x).

Let's assume we have the following "Note" model:

{
  "name": "Note",
  "properties": {
    "title": {
      "type": "string",
      "required": true
    },
    "content": {
      "type": "string"
    },
    "userId": {
      "type": "number"
    }
  },
  "relations": {
      "user": {
          "type": "belongsTo",
          "model": "User",
          "foreignKey": "userId"
      }
  }
}

Now, to include "user" property (which is a belongsTo relation of Note) in the response when you create (POST) a Note you have two options.

Option #1 (Recommended): Create a custom remote method and hide the default method in your model's script file. In this case your note.js file should look something like:

module.exports = function (Note) {
    // Hide the default 'create' remote method
    Note.disableRemoteMethod('create', true);

    // Add a custom 'customCreate' remote method 
    Note.remoteMethod('customCreate', {
        description: 'Create a new instance of the model and persist it into the data source.',
        accessType: 'WRITE',
        accepts: [
            {
                arg: 'data',
                type: 'object',
                model: 'Note',
                allowArray: true,
                description: 'Model instance data',
                http: { source: 'body' },
            },
            { arg: 'options', type: 'object', http: 'optionsFromRequest' },
        ],
        returns: { arg: 'data', type: 'Note', root: true },
        http: { verb: 'post', path: '/' },
        isStatic: true,
    });

    Note.customCreate = function (data, options, cb) {
        Note.create(data, options, function(err, newObj) {
            if (err) {
                cb(err);
            }
            else {
                // here we try to load the user value
                newObj.user(function (err, user) { 
                    if (user) {
                        // if we found a user we add it to __data, so it appears in the output (a bit hacky way)
                        newObj.__data.user = user;
                    }

                    cb(err, newObj);
                });
            }
        });
    };
};

I would recommend using this option because you achieve what you need with minimal changes in the default logic of the loopback model, i.e. all the default methods like create, upsert, etc. continue to have default behavior.

Option 2: Use 'after save' operation hook (be careful with this approach as it changes the way how create, upsert, upsertWithWhere and other default methods work)

In this case your note.js file should look something like:

module.exports = function (Note) {
    Note.observe('after save', function (ctx, next) {
        ctx.instance.user(function (err, user) {
            ctx.instance.__data.user = user;
            next();
        });
    });
};

The second option has less code, but as I mentioned before you should be very careful using it because it will change the behavior of default "create" method of the model. I.e. 'after save' action will be executed each time you call Model.create, Model.upsert, etc. It will also slow down these operation as you add additional select query in the 'after save' hook.

Upvotes: 2

Related Questions