Skip to content

allowArray flag for remoteObject accept#369

Merged
davidcheung merged 2 commits into
masterfrom
allow-array
Oct 19, 2016
Merged

allowArray flag for remoteObject accept#369
davidcheung merged 2 commits into
masterfrom
allow-array

Conversation

@davidcheung

Copy link
Copy Markdown
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
Copy Markdown
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

bajtos commented Oct 13, 2016

Copy link
Copy Markdown
Member

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
Copy Markdown
Contributor Author

@slnode test please

@davidcheung

Copy link
Copy Markdown
Contributor Author

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

@bajtos bajtos left a comment

Copy link
Copy Markdown
Member

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!

Comment thread lib/http-context.js Outdated
var httpFormat = o.http;
var name = o.name || o.arg;
var val;
var coercionOptions = {};

Copy link
Copy Markdown
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');

Comment thread lib/http-context.js Outdated

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

Copy link
Copy Markdown
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).

Comment thread lib/types/object.js
err = errorArrayItemsNotAnObject();
return;
}
});

Copy link
Copy Markdown
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;

Comment thread lib/types/object.js Outdated
}

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

Copy link
Copy Markdown
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
Copy Markdown
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
Copy Markdown
Contributor Author

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

@bajtos bajtos left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Few more comments, PTAL

Comment thread lib/shared-method.js Outdated
* @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
Copy Markdown
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;
};

Comment thread lib/shared-method.js Outdated
var name = desc.name || desc.arg;
var uarg = SharedMethod.convertArg(desc, args[name]);

var coercionOptions = {};

Copy link
Copy Markdown
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.

Comment thread lib/shared-method.js Outdated
* @return {*} Coerced argument.
*/
function validateInputArgument(uarg, desc, ctx) {
function validateInputArgument(uarg, desc, ctx, options) {

Copy link
Copy Markdown
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?

Comment thread lib/types/object.js Outdated

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

Copy link
Copy Markdown
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

@bajtos bajtos left a comment

Copy link
Copy Markdown
Member

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.

Comment thread lib/shared-method.js Outdated
* 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
Copy Markdown
Member

Choose a reason for hiding this comment

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

please remove

Comment thread lib/shared-method.js Outdated
/**
* build conversion options from remote's' args
*
* @param arg (remote args such as `accepts`)

Copy link
Copy Markdown
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.

Comment thread lib/shared-method.js Outdated
*
* @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
Copy Markdown
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
Copy Markdown
Contributor Author

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

@davidcheung

Copy link
Copy Markdown
Contributor Author

@slnode test please

2 similar comments
@davidcheung

Copy link
Copy Markdown
Contributor Author

@slnode test please

@davidcheung

Copy link
Copy Markdown
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
Copy Markdown
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)

2 participants