Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best practice to change default blueprint actions in sails.js

I'm looking for an answer to what is the best practice to customize default sails.js CRUD blueprints. The simple example of what I mean is let's say I need to create SomeModel, using standard blueprint POST \someModel action, and also I want to get information about authenticated user from req object and set this property to req.body to use values.user.id in beforeCreate function:

module.exports = {

  attributes: {
    // some attributes
  },

  beforeCreate: function (values, cb) {
    // do something with values.user.id
  }
};

I'm very new to sails.js and don't want to use anti-patterns, so I'm asking for inputs on what is the right way to handle such cases. Also it would be great to have some good resources on that topic.

like image 483
dim0_0n Avatar asked Feb 21 '16 19:02

dim0_0n


1 Answers

There are a few options open to you which you've identified, and as usual, it depends on your use case. Here are some thoughts on the three options you listed in your comment:

  1. Override controller/create - Of the three, this is the best option because it doesn't clog up code in routes or policies for a single instance.
  2. Write controller/action and add to config/routes.js - While this works, it defeats the purpose of using blueprints, and you have to do all the code in option 1 plus making your routes code messier.
  3. Apply a policy for a single create action - To do this, you will not only have to clutter up your /policies folder but also your policies.js file. This is more code AND it puts the logic for one controller method in two separate places, neither of which is the controller.

Out of these three, option 1 is the best because it contains the code to its context (the controller) and minimizes written code. This is assuming that you only want to alter the create method for one model.


Side note:

As an example of how your use case determines your implementation, here is how I've set my Sails app up which has a few REST routes, each of which responds differently based on the user calling the route (with a valid Facebook token):

  1. Only uses blueprint action routes (not blueprint REST routes)
  2. First goes through the policies: '*': ['hasFBToken', 'isTokenForMyApp', 'extractFBUser', 'extractMyAppUser'] which store fbuser, myappuser, and other variables in req.body
  3. At this point, my controller function (e.g. controller.action()) is called and can access information about that user and determine if it has the correct permissions to do CRUD.

Pros of this system:

  • All code for each CRUD operation is contained within its controller function
  • Minimal to no code in routes.js (no code) or policies.js (one line) or /policies
  • Works well with API Versioning (e.g. controllers/v1.0/controller.js), which is much easier to do with versioned controllers than versioned models. That means that I can create a new API version and simply by creating a controller in /v2.0 with a function action(), calls such as POST /v2.0/controller/action will exist with no extra routing needed.

Hopefully this example helps illustrate how design decisions were made to offer functionality like API versioning and consolidate code in its specific context.

like image 175
smileham Avatar answered Nov 05 '22 13:11

smileham