Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@davidcheung
Copy link
Contributor

fixes #360

In loopback 2.x endpoints supported batch create which passes
an Array of Objects into the endpoint that expects Objects,
this is nolonger allowed in 3.x's stricter coercion
In order to maintain backwards compatiability, this is a short term
fix to allow endpoints to accept Array of Objects with the allowArray

@davidcheung davidcheung self-assigned this Oct 11, 2016
@davidcheung davidcheung added #review and removed #wip labels Oct 11, 2016
@davidcheung
Copy link
Contributor Author

@bajtos PTAL, this is so hacky 😭
any thoughts on how to improve the implementation?

@bajtos bajtos self-assigned this Oct 13, 2016
@bajtos
Copy link
Member

bajtos commented Oct 13, 2016

PTAL, this is so hacky

Yeah, I agree.

How about adding an options object to all three converter methods (fromSloppyValue, fromTypedValue, validate)? It will require one-time change in all converters to ensure options are passed down to other methods (please send it in a standalone commit), but then the implementation of allowArray should be very simple.

Thoughts?

@davidcheung davidcheung force-pushed the allow-array branch 2 times, most recently from a94f021 to 073b003 Compare October 14, 2016 19:01
@davidcheung
Copy link
Contributor Author

@slnode test please

@davidcheung
Copy link
Contributor Author

@bajtos PTAL again, i think this is better this time

Copy link
Member

@bajtos bajtos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, this second version looks much better!

var httpFormat = o.http;
var name = o.name || o.arg;
var val;
var coercionOptions = {};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would personally prefer conversionOptions over coercionOptions, because we already use "conversion" in TypeRegistry-related code, see e.g.

assert(typeof typeName === 'string' && typeName,
'typeName must be a non-empty string');
assert(typeof converter === 'object' && converter,
'converter must be an object');
assert(typeof converter.fromTypedValue === 'function',
'converter.fromTypedValue must be a function');
assert(typeof converter.fromSloppyValue === 'function',
'converter.fromSloppyValue must be a function');
assert(typeof converter.validate === 'function',
'converter.validate must be a function');


var typeConverter = ctx.typeRegistry.getConverter(o.type);
if (o.allowArray)
coercionOptions.allowArray = o.allowArray;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am proposing to extract these two lines into a shared method, so that there is only one place to change if we need to add more options in the future. E.g. a static method SharedMethod.getConversionOptionsForArg(o).

err = errorArrayItemsNotAnObject();
return;
}
});
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this may be a bit cleaner:

var hasInvalidItems = value.some(function(item) {
  return typeof item !== 'object' || Array.isArray(item) || item === null;
});

return hasInvalidItems ? errorArrayItemsNotAnObject() : null;

How about Dates as the array items, I think we should reject them too. Can we perhaps reuse validate inside the forEach/some callback?

var self = this;
var hasInvalidItems = value.some(function(item) {
  return !self.validate(item/* no options (?) */);
});
return hasInvalidItems ? errorArrayItemsNotAnObject() : null;

}

function errorArrayItemsNotAnObject() {
var err = new Error(g.f('Array items are not an object.'));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about Some of array items are not an object ?


describe('json body - object - allowArray: true', function() {
verifyTestCases({ arg: 'data', type: 'object', allowArray: true }, [
// should accept regular objects, plus array of objects
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you please add few cases for "regular objects"?

@davidcheung
Copy link
Contributor Author

oh nice, changed now auto collapse again, @bajtos PTAL
applied the feedback and also added test case in json-form and customClass

Copy link
Member

@bajtos bajtos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Few more comments, PTAL

* @param optionsObj (optional parameter that gets operated on if you provide it)
* @returns optionsObj(options to pass to typeConverter methods, eg: validate, fromTypedValue)
*/
SharedMethod.getConversionOptionsForArg = function(arg, options) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Modifying input parameters is a bad practice that's better to be avoided.

SharedMethod.getConversionOptionsForArg = function(arg) {
  var options = {};
  // ...
  return options;
};

var name = desc.name || desc.arg;
var uarg = SharedMethod.convertArg(desc, args[name]);

var coercionOptions = {};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use SharedMethod.getConversionOptionsForArg, rename coercionOptions to conversionOptions.

* @return {*} Coerced argument.
*/
function validateInputArgument(uarg, desc, ctx) {
function validateInputArgument(uarg, desc, ctx, options) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rename options to conversionOptions?


validate: function(ctx, value) {
validate: function(ctx, value, options) {
var _self = this;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why the leading underscore? AFAIK, we use self everywhere else in LoopBack.

@davidcheung davidcheung force-pushed the allow-array branch 2 times, most recently from ebebf61 to e53a511 Compare October 18, 2016 14:01
Copy link
Member

@bajtos bajtos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The jsdoc comment is not correct, the patch LGTM otherwise. No more review is needed.

* build conversion options from remote's' args
*
* @param arg (remote args such as `accepts`)
* @param optionsObj (optional parameter that gets operated on if you provide it)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please remove

/**
* build conversion options from remote's' args
*
* @param arg (remote args such as `accepts`)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@param {Object} arg Definition of accepts/returns argument.

*
* @param arg (remote args such as `accepts`)
* @param optionsObj (optional parameter that gets operated on if you provide it)
* @returns optionsObj(options to pass to typeConverter methods, eg: validate, fromTypedValue)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@returns {Object} Options object to pass to type-converter methods,
   e.g `validate` or `fromTypedValue`.

@davidcheung
Copy link
Contributor Author

ci failing due to http-auth dropping node 10 / 12 support 😭 gevorg/http-auth@0097ed6

@davidcheung
Copy link
Contributor Author

@slnode test please

2 similar comments
@davidcheung
Copy link
Contributor Author

@slnode test please

@davidcheung
Copy link
Contributor Author

@slnode test please

David Cheung added 2 commits October 19, 2016 10:37
options are now available in functions
- fromTypedValue
- fromSloppyValue
- validate
In loopback 2.x endpoints supported batch create which passes
an Array of Objects into the endpoint that expects Objects,
this is nolonger allowed in 3.x's stricter coercion
In order to maintain backwards compatiability, this is a short term
fix to allow endpoints to accept Array of Objects with the allowArray
@davidcheung
Copy link
Contributor Author

@slnode test please

@davidcheung davidcheung merged commit 6c7e23a into master Oct 19, 2016
@davidcheung davidcheung deleted the allow-array branch October 19, 2016 15:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Allow both object and array values for an argument (create/createMany)

3 participants