question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Refactoring: API/Model layer - pass options object

See original GitHub issue

Problem description

There are two problems.

API layer and pipeline

If you take a look at this commit, you will see that the way our pipeline tooling works, clashes with how our API layer works. The API layer always needs access to the modified options object. These modifications happen in stages e.g. permissions are getting added. Furthermore, the pipeline tooling requires us to return the options in each function call, see. Furthermore, it’s a mixed design, because we pass an argument by reference, we modify it, but we have to return it. That is super confusing. Either you get an argument, you create your own object, eat from the argument and return the new object or you follow the pattern of object modification.

  something(options) { 
    options.a = 'lol';
    returns options; 
  }
  
  beautiful(options) { 
     assert.true(options.a); 
     returns options; 
  }
  
   pipeline([something, beautiful], options)

Model layer and the access plugin

The model layer uses two different techniques to determine the permissions of a model query. The access rules plugin and the direct check. The access plugin requires us to pass the permission context into the .forge function, which instantiates a new model. Doing that allows us to use a helper function like isPublicContext. Right now, it’s almost never used and we have permission checks in the whole system, not just in the model layer. Plus bookshelf follows the concept of the options pattern very strong. You always have to pass your options into function calls e.g. .fetch(options). The outcome of this is that on each model hook we are able to access our options. So having access to this._context, is not useful, because we can access the options anyway in each function.

This is how the options object get’s passed through the system

Questions

What is the best way to pass it around? How to keep track of the API options object? Get rid of .forge?

Solutions

Replace pipeline in the API layer

This requires us to make even more usage of the options pattern.

  permissions(options) { 
    options.context = {...};
  }
  
  query(options) { 
     models.Post.edit(options)
       .then(function(updatedModel) {
           options.response = updatedModel;
       });
  }
  
  pipeline([something, beautiful], options)
       .then(function(options) {
  });

The full options object would look like this:

{
  context/permissions: {},
  data: {},
  params: {},
  response: {},
  transacting: {}
}

Remove the access plugin

Remove the plugin for now and use direct context checks. The future goal here is to make the context object very powerful e.g. by creating a class e.g. new Context(), which is passes within the options object, which then allows you to call options.context.isPublic().

Tasks

Future

We would like to write an issue for transforming the context object into a class. And another issue about who is responsible to calling toJSON of a model - we have very heavy mixture of this concept.

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Comments:7 (5 by maintainers)

github_iconTop GitHub Comments

1reaction
Sjobomcommented, Apr 6, 2018

@kirrg001 No unfortunately I don’t think so 😕 Sorry for not communicating this before. Me and my friends did some work which can be seen in these pull requests.

We replaced the pipeline in most parts of the api with the new “sequential.js” which in comparison to the old “pipeline.js” does not return the options object to the next task in the pipeline. Instead we add parameters that is needed later in the execution to the options object like we discussed.

0reactions
kirrg001commented, Oct 19, 2018

Closing this issue in favor of #9866.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Introduce Parameter Object - Refactoring.Guru
In all method calls, pass the object created from old method parameters to this parameter. Now start deleting old parameters from the method...
Read more >
Refactor for accepting Marshmallow and other marshaling ...
Before I design the abstraction layer I'd like to make sure I know exactly what the internal API needs to be able to...
Read more >
What's the best way to refactor a method that has too many (6+ ...
"Introduce Parameter Object" refactoring. See the Refactoring Catalog. The idea is that you take some of the parameters you're passing and ...
Read more >
Your API and View Models Should Not Reference Domain ...
Client facing models typically reside in the UI layer as ViewModels or ApiModels, or they may be called DTOs (Data Transfer Objects).
Read more >
5. Separation of Concerns - Programming JavaScript ... - O'Reilly
Separation of concerns is the idea that each module or layer in an application should ... The environment object (optional) is the primary...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found