Code Monkey home page Code Monkey logo

meteor-simple-schema's Issues

sharing primary document attributes (schema parts)

The README shows an example where a "AdressSchema" sub-schema gets embedded into multiple document attributes.
However, because DDP syncing operates on the level of document attributes:

Is there also a proper way to use/share a schema for defining first level document attributes accross multiple collections (not embedded subfields), so that Meteor can sync/transfer the documents attributes individually?

Multiple RegEx Per Key

It was mentioned in #5 that regEx should support multiple regular expressions for a single schema key. This seems like a good idea. Might be best to name them rather than using an array, and then those names can be used for custom messages:

MySchema = new SimpleSchema({
  password: {
    type: String,
    regEx: {
      numbers: twoNumbersRegEx
    }
  }
});

MySchema.messages({
    'regEx.numbers': "[label] must have two numbers"
});

Async callback for "valueIsAllowed"

I think that "valueIsAllowed" should provide async features on the client side. It may be helpfull to check values (using meteor methods), that can be verified on the server side only (for security and app's architecture reasons).

Collection Question

Hello,

I think I am missing something. Where do you create your collection and how do you tie it to the schema? (without using collection2)

Thanks

Possible problems with validation of embedded objects?

It seems that (server side?) updates fail when an it is done on a collection that has "Object" fields.

If you do something like:

@col = new Meteor.Collection2 "col",
    schema:
        "name":
            type: String
        "embed":
            type: Object
        "embed._id":
            type: String

The following will fail:

col.update {_id: ...},{$set:{name:"Updated name"}}

More specifically, you'll get an "invalid key" for "embed._id", even though it is simply not touched by the update. I guess this can be circumvented by using the _collection field directly, but that doesn't sound like what should happen here. (Sorry for using Coffeescript syntax.)

Since this specifically interacts with "partial validation" scenario's where not all fields need to be validated, it's hard to think of a way to trigger this directly in simple-schema.

Default Values

Is there a way to set default values? Not sure if the schema is the place to set defaults but I'm thinking it would be nice in some cases.

default value

I miss an option defaultValue which would be inserted by the clean method. I know that collection2 delivers a autoValue but things aren't always inserted into the database and even then it takes some of the same logic every time I want to implement a default value.

Collapsing Update Objects

There are a number of areas where the variety of possible modifier formats makes things confusing for validation, or for extra checks that are done in collection2. A good solution might be to collapse update objects in a manner similar to what is currently done with insert objects. In other words, rearrange keys in the modifier object so that the first level of keys matches the format of the schema keys. Then have all the modifier objects below that. Certain modifier objects might make this difficult, so we'll have to see if it's possible.

An example:

{
  $set: {
    'name.first': Foo,
    'name.last': Bar,
    age: 45
  },
  $inc: { updates: 1 },
  $push: { scores: 89 }
}

Is run through the collapse function and becomes:

{
  'name.first': { $set: Foo },
  'name.last': { $set: Bar },
  age: { $set: 45 },
  updates: { $inc: 1 },
  scores: { $push: 89 }
}

This makes validation much easier because we now only have to loop through the first level and look from schema rules, and then check for any operators under that and perform appropriate validations. This will make it much easier to implement validation checks for the remaining operators that are not currently supported. Also, the rearranged object can be passed to custom validation functions, autoValue functions, etc. to make it much easier for those to validate, set values, etc.

Entering a Date

What is the correct way to set a minimum date? Also how should we insert a date to to a collection?

Validate Custom Objects

When the type option is a custom object type (or array of them), and that custom type exposes a simpleSchema() method, we should validate custom objects during validation, and merge any errors into the main invalidKeys array.

In addition to being generically useful, this will specifically help with collection2 development to support relationships between collections.

States for validation results

It would be nice if there were more than two validation states (error or no error). I like using four message classes: error, success, warning, and info. For example, I might use warning to tell someone their password isn't very strong while still letting them use it. I also use an info class to visually let the user know that a field is required when they haven't entered anything into it yet.

Callbacks for Strings

I'm thinking that a callback for string fields like messages or labels would help implement multiple languages. Think of that:

label: __.bind(__, "some.language.key")
// the language function of the i18n package bound with the key so its called when needed

This would allow Meteor.render to dynamically change the label when the language changes. To make it compatible the label function might have to be wrapped in an object with a toString method.

Cutom validation problem

Hi,

I think I have found a problem with the example at "Validating One Key Against Another". Using that example just throws:

Error: Invalid definition for confirmPassword field.
     at packages/simple-schema/simple-schema.js:81
     at Function._.each._.forEach (packages/underscore/underscore.js:87)
     at SimpleSchema (packages/simple-schema/simple-schema.js:78)
     at app/both/collections/modules/accounts.js:1:49
     at app/both/collections/modules/accounts.js:71:3
     at /home/j/www/sandbox.arandu.meteor/src/.meteor/local/build/programs/server/boot.js:155:10
     at Array.forEach (native)
     at Function._.each._.forEach (/home/j/.meteor/tools/09b63f1ed5/lib/node_modules/underscore/underscore.js:79:11)
     at /home/j/www/sandbox.arandu.meteor/src/.meteor/local/build/programs/server/boot.js:82:5

I'm using the following schema:

AccountsSS = new SimpleSchema({
  "username": {
    type: String,
    label: 'Username'
  },
  password: {
    type: String,
    label: "Enter a password",
    min: 8
  },
  confirmPassword: {
    type: String,
    label: "Enter the password again",
    min: 8,
    custom: function () {
      if (this.value !== this.field('password').value) {
        return "passwordMismatch";
      }
    }
  }
});

Storing objects that cannot be defined

Hi, we are creating an application that needs to save user generated data. The user uploads a csv file and we create a document for each of the rows of the csv file. We later use the data in the csv in lists, edit screens and to pass to other parts of the application.

The problem we are having is that every csv file can have a different column definition. This makes it almost impossible to validate the rest of the docment we are inserting, as simple-schema does not allow black box objects (the csv data needs to be a key-value object).

Example pseudocode:

CSV = new Meteor.Collection2('csv', {
    schema: {
        uploadId: {
            type: String,
            label: "data is part of this upload"
        },
        data: {
            type: Object,
            label: "Answers in csv"
        }
    }
});

csv_data = {
    uploadId: "1234567890",
    data: {
                COL1: 1,
                COL2: "some string",
                COL3: 3.324,
                COL4: 4
    }
};

Would there be no way of telling simple-schema to just accept the object and ignore what else is in there? It is not an option for us to JSON.stringify the data as suggested earlier as we use this data all over our application, and very often want to access the data from a column directly (data.COL1 for instance) in Mongo queries (in C++ applications). The csv data can be a very large object.

Custom validation message for array elements

I'm trying to write a custom validation message for keys in an array of sub-schema elements. The message keys are matched literally, while my key includes the array index of the element: groups.0.name. Here is the (simplified) relevant schema code:

var group = new SimpleSchema({
  name: {
    type: String
  }
});

var schema = new SimpleSchema({
  groups: {
    type: [group]
  }
});

I have two potential solutions in mind:

Solution 1. It would be great if I could either add a message to the messages object of the group object from the above example, which will be automatically picked up when validating against the parent schema schema. This solution could also be taken into account, when working on issue #46. Like this:

group.messages({
  'required name': 'my_error_message'
});

Solution 2. Add a message to the messages object of the schema object with a wildcard for matching the array index. Example:

schema.messages({
  'required groups.$.name': 'my_error_message'
});

Validating elements of array

Right now The following wouldn't work:

  tags: {
    type: [String],
    label: "Tags",
    min: 0,
    max: 12
  },
  "tags.$": {
    min: 2,
    max: 64
  }

It would give you error saying 'tags.$ is required'.

Regex validation causes Max validation to be ignored on String

If there is a Regex check on a key, the Max attribute does not seem to be validated against -- e.g. in the following, isValid() still allows a string with more than 15 characters to pass validation:
username: {
type: String,
min: 3,
max: 15,
regEx: /^[a-z0-9_]+$/
}

This might happen for other types as well, but I haven't looked into this.

Referencing documents

Hello, this is more a question than an issue:
what "type" should be set when we want to reference another doc within a Schema?

I've tried:

schema: {
  userId: {
    type: Meteor.Collection.ObjectID
  }
}

But got a failed validation.

Thanks!

Support Additional Update Operators

This is to track progress adding support for additional update operators beyond $set and $unset.

The following operators need to be parsed and understood (but not necessarily validated) by the validation and cleanup functions in simple-schema:

  • $setOnInsert (treat this just like $set, merge contents with contents of $set)
  • $rename
  • $inc
  • $addToSet
  • $push
  • $pushAll (deprecated but might still work?)
  • $pull
  • $pullAll
  • $pop
  • $each (used with $push or $addToSet; probably remove the $each and treat like setting directly)
  • $slice

The following operators need to be validated as best they can by simple-schema:

  • $setOnInsert (treat this just like an insert)
  • $rename (make sure old name is not required and new name is in schema)
  • $addToSet (check allowed values and validate each item)
  • $push (check allowed values and validate each item)
  • $pushAll (deprecated but might still work?) (throw error)
  • $each (used with $push or $addToSet; probably remove the $each and treat like setting directly)

And all except $setOnInsert will probably need some extended validation added in the collection2 package.

Context sensitive valueIsAllowed

There should be a way to validate fields that rely on other fields. For example, a verify password or verify email field needs to be matched against another value. Maybe there could be a valueIsAllowed function that was passed the entire object instead of just the value?

Validation Messages are defined at the Schema level but apply to all Schemas

With the following validation message definitions "regEx Results.name message" is used for both regEx Races.name & regEx Results.name because it was defined second replacing "regEx Races.name message".

Races.simpleSchema().messages({
  'regEx name': "regEx Races.name message"
});
Results.simpleSchema().messages({
  'regEx name': "regEx Results.name message"
});

First part of this issue is more bug, messages should be defined on global SimpleSchema object if they effect all schemas:

SimpleSchema.messages({
  'regEx name': "regEx name message"
});

Second part of this issue is more enhancement. It'd be great to be to able to use the same key name on two different schemas and retain the ability to have different error messages by specifying the schema name:

SimpleSchema.messages({
  \\ effects regEx error message for all keys equal to 'name' regardless of schema
  'regEx name': "regEx name message",
  \\ effects regEx error message only for key equal to 'name' on 'Results' schema
  'regEx Results.name': "regEx Results.name message"
});

TypeError: Cannot read property 'type' of undefined

Getting a new error in 0.2.31

  /lib/node_modules/fibers/future.js:173
            throw(ex);
                 ^
  TypeError: Cannot read property 'type' of undefined
    at packages/simple-schema/simple-schema.js:575
    at Function._.each._.forEach (packages/underscore/underscore.js:82)
    at expandSchema (packages/simple-schema/simple-schema.js:573)
    at packages/simple-schema/simple-schema.js:549
     at Array.forEach (native)
     at Function._.each._.forEach (packages/underscore/underscore.js:79)
     at mergeSchemas (packages/simple-schema/simple-schema.js:542)
     at SimpleSchema (packages/simple-schema/simple-schema.js:39)
     at Meteor.Collection (packages/collection2/collection2.js:45)
     at __coffeescriptShare (packages/reaction-shop/common/collections.coffee:381:15) 

I see it's from a little recent funkiness of mine:

@Orders = new Meteor.Collection "Orders",
  schema = new SimpleSchema([Cart,
    additionalField:
      type: String
      optional: true
    status:
      type: String
  ])

Guess, you might want to catch this error.

Empty string as acceptable value on non-optional field?

What is the correct way to allow an empty string ('') to validate? I haven't marked this field as optional, but I set min to 0. I'd expect it to reject my insert if I passed null, undefined, or omitted the field entirely, but it seems to also reject an empty string. Is this by design? For certain applications, might it make sense to allow empty string as an acceptable value? I'm willing to try to work around this, but wanted to be sure it's a design decision that I can learn, and not a bug. Thanks!

Not typeconverting values of nested objects

Using simple-schema v0.2.10

Simple-schema does not seem to be typeconverting some string values of a nested object into numbers/decimal numbers when I call clean. I was looking through the code of simple-schema.js and it's something in here:

//clean
  newDoc = {};
  _.each(cDoc, function(val, key) {
    var okToAdd = true;

    //filter
    if (options.filter === true) {
      okToAdd = self.allowsKey(key);
    }

    if (okToAdd) {
      //autoconvert
      if (options.autoConvert === true) {
        var def = self._schema[key];
        if (def) {
          var type = def.type;
          if (_.isArray(type)) {
            type = type[0];
          }
          if (looksLikeModifier(val)) {
            //convert modifier values
            _.each(val, function(opVal, op) {
              if (_.isArray(opVal)) {
                for (var i = 0, ln = opVal.length; i < ln; i++) {
                  opVal[i] = typeconvert(opVal[i], type); //typeconvert
                }
              } else if (_.isObject(opVal) && ("$each" in opVal)) {
                for (var i = 0, ln = opVal.$each.length; i < ln; i++) {
                  opVal.$each[i] = typeconvert(opVal.$each[i], type); //typeconvert
                }
              } else {
                opVal = typeconvert(opVal, type); //typeconvert
              }
              val[op] = opVal;
            });
          } else if (_.isArray(val)) {
            for (var i = 0, ln = val.length; i < ln; i++) {
              val[i] = typeconvert(val[i], type); //typeconvert
            }
          } else {
            val = typeconvert(val, type); //typeconvert
          }
        }
      }

      newDoc[key] = val;
    }
  });

If I understand correctly, looksLikeModifier(val) needs to be true in order to get to this line: } else if (_.isObject(opVal) && ("$each" in opVal)) { which I think is what would typeconvert the nested values? I don't really understand what the "$each" is except that opVal is the first argument to the iterator of the _.each call and represents the current element. http://underscorejs.org/#each

Some of the values i'm trying to convert include negative integers and negative decimals.

Let me know what you think and if i'm totally misunderstanding what's going on and doing something wrong.

Allow function for min/max

For cases where runtime calculations are necessary for min/max, it would be nice if min and max could be a function that returns the min/max value. This would be most useful for dates, where you might want a minimum of "today at 8 AM" for example.

min: and max: constraint don't detect 0

hi,

I tried to set a positive constraint for a Number value:

MySchema = new SimpleSchema({
    area: {
         type:Number,
         min:0
    }
}

but validation does not detect e.g.

obj={area:-1};
ssContext.validate(obj);

as in simple-schema-contexts.js check is:

} else if (max && max < keyValue) {
      invalidKeys.push(errorObject("maxNumber", keyName, keyValue, def, ss));
    } else if (min && min > keyValue) {
      invalidKeys.push(errorObject("minNumber", keyName, keyValue, def, ss));

thus ignoring 0 limited min and max range.

I fixed this with

} else if (max !== undefined && max < keyValue) {
      invalidKeys.push(errorObject("maxNumber", schemaKeyName, keyValue, def, ss));
    } else if (min !== undefined && min > keyValue) {
      invalidKeys.push(errorObject("minNumber", schemaKeyName, keyValue, def, ss));

Should something else be changed in addition?

Jyrki

Validation of subdocuments

Hi, I have an issue which I think is a bug but it may also be my misunderstanding.

Here's my case. With schema as this:

Pet = new SimpleSchema({
    name: {
        type: String
    }
});

Person = new SimpleSchema({
    name: {
        type: String
    }
});

Family = new SimpleSchema({
    pets: {
        type: [Pet]
    },
    kids: {
        type: [Person]
    },
    parents: {
        type: [Person]
    },
    id: {
        type: String
    }
});

Validation seems to work for non-array properties just as one could imagine:

sc = Family.newContext();
sc.validate({$set:{id:"12"}}, {modifier:true});
sc.isValid(); // returns true

sc.validate({$addToSet:{pets:{name:"Felix"}}}, {modifier:true});
sc.isValid(); //false
sc.invalidKeys(); 

Now, the last statement returns

"[{"name":"kids.$.name","type":"required","message":"Name is required"},{"name":"parents.$.name","type":"required","message":"Name is required"}]"

which I interpret as it expects the object to be full schema compatible, even though I think it should validate only against "Pet" schema.

I encountered this with Collections2, where it's very hard to add an element into a subdocument array when schema is complex. Basically only using $set to replace the full array seems to work.

Or do I get it wrong?

Thanks,
Jyrki

[Enhancement Request]: Ability to define virtual fields within Simple Schema

A powerful feature of Collection2 is the ability to define schema structure outside the collection definition.

Coupled with the ability to combine multiple schema structures within Simple Schema, we have a good mechanism for keeping the code dry, abstract and clean.

Virtual fields are a great addition to Collection2. But consider a use case where we have a base schema (e.g. createdAt, createdBy, updatedAt, updatedBy) which we include in all our collections through their respective schemas.

And consider for each document in any collection, I would like to have a virtual field that gives me the email address for the user who has created the document.

In its current form, we need to include such virtual field in every collection or hack it using _.extend etc.

It would be a great feature if one could define virtual field at the schema level as well.

SchemaRegEx.Email is not entirely valid

SchemaRegEx.Email is not correnct.

However this needs to be discussed. Technically the address root+something@localhost is a valid email and will be accepted by the browsers input type email. Maybe multiple pre made expressions are needed to fill what the developer needs.

I eg. like to allow the '+' as it allows the user (if he knows about that) to figure out where the mail came from.

Then again I dislike allowing domains that don't have a '.' as in the normal case we are not in an intranet and such mails aren't what we want. However for the intranet case this should be there too.

Clean is removing actual fields whose names are subsets of virtual fields.

position.slice(0, p.length) === p
https://github.com/aldeed/meteor-simple-schema/blob/master/mongo-object.js#L135

Collection2 insert doValidate calls simple-schema's clean which calls mongo-object's removeValueForPosition intending to remove virtual fields, but due to the line above, which I don't understand the purpose of, it also removes actual fields whose names are subsets of virtual fields.

For example, I have a virtual field called distancePath & an actual field called distance, they both get removed and the insert fails. I'm not sure which version introduced this bug, but it was working until I upgraded today so it is definitely a regression:

autoform v0.4.10 - v0.4.13
collection2 v0.3.3 - v0.3.7
simple-schema v0.2.30 - v0.2.34

invalidkeys() not set when separately constructed schema is included in collection definition of collection2

The following is a schema design that incorporates a common base schema. (autovalues etc may not make sense, I just used them to see if features are interchangeable between collection2 and simple-schema)

/********************************
Base Collection Schema
********************************/
CoolProject.Collections.BaseSchema = new SimpleSchema({
  active: {
    type: Boolean
  },
  createdAt: {
    type: Date,
    min: new Date(),
    autoValue: function() {
      if (this.isInsert) {
        return new Date;
      } else if (this.isUpsert) {
        return {$setOnInsert: new Date};
      } else {
        this.unset();
      }
    },
    denyUpdate: true
  },
  updatedAt: {
    type: Date,
    min: new Date(),
    autoValue: function() {
      if (this.isUpdate) {
        return new Date();
      }
    },
    denyInsert: true,
    optional: true
  }
});

/********************************
Tag Collection Schema
********************************/
CoolProject.Collections.TagsSchema = new SimpleSchema([
  CoolProject.Collections.BaseSchema,
  {
    title: {
      type: String,
      label: 'Title',
      min: 5,
      max: 10
    },
    slug: {
      type: String,
      label: 'Slug',
      autoValue: function() {
        var title = this.field("title");
        if (title.isSet) {
          return URLify2(title.value);
        } else {
          this.unset();
        }
      }
    }
  }
]);

/********************************
The Actual Collection
********************************/
CoolProject.Collections.Tags = new Meteor.Collection('tags', {
  schema: CoolProject.Collections.TagsSchema,
  virtualFields: {
    virtualTest: function(tag) {
      return tag.title + ' // ' + tag.slug;
    }
  }});

Then on the browser console, I test the code by inserting some values using:

/********************************
Browser Console
********************************/
CoolProject.Collections.Tags.insert(
  {/*  WRITE SOME DOC HERE */},
  function(err,res) {
    if (err) return CoolProject.Collections.Tags.simpleSchema().namedContext().invalidKeys();   
  }
);

If the document is valid, it passes successfully through and I receive back the inserted document id. The autovalue, and nesting seems to be working. ( Except that the virtual field does not work, but it is already reported on another issue #47 )

THE PROBLEM:

If the doc is invalid (e.g. missing active or too short a title) then all I receive on the console output returns undefined whereas an array of error objects should have returned. This is reproducible on both 0.2.17 and 0.3.0

getArrayInfoForKey(line 150) and affectsGenericKey(line 334) with arrays in mongo-object.js

Assuming that you have an array field in your Collection2 schema like this one:

 member_ids: {
            type: Array(String),
            label: "liste of member Ids",
            autoValue: function () {
                console.log("this",this)
                console.log("this.field('member_ids')",this.field("member_ids"))
               }
}

When I do a $pull:{member_ids:"xyz"} (or an $addToSet),I assumed that
this.operator is $pull,
this.value is xyz
this.isSet() is true.

But this.operator and this.value are undefined and this.isSet() is false

this.isSet() is false because affectsGenericKey is looking for member_ids in _genericAffectedKeys but there is only member__ids.$. (line 342)

this.operator and this.value are undefined because getArrayInfoForKey() never returns a value due to getValueForPosition(line 86) which never returns a value too.

In collection2.js (line 462 getAutoValues)

...
var keyInfo = mDoc.getArrayInfoForKey(fieldName) || mDoc.getInfoForKey(fieldName) || {};
....
isSet: mDoc.affectsGenericKey(fieldName),
....
value: keyInfo.value,
 operator: keyInfo.operator,
field: function(fName) {
        var keyInfo = mDoc.getArrayInfoForKey(fName) || mDoc.getInfoForKey(fName) || {};
        return {
          isSet: (keyInfo.value !== void 0),
          value: keyInfo.value,
          operator: keyInfo.operator
        };
      }
    }, doc);

conditional optional

Is there any way to have a 'conditional optional'? I'm trying to make a situation work where a key would only be required when another key is set.

new SimpleSchema({
  firstname: {
    type: String,
    label: "First name",
    optional: true
  },
  lastname: {
    type: String,
    label: "Last name",
    optional: true
  }
})

Considering this schema. How would I go ahead and make lastname required or optional: false when and only when firstname is set?

Label improvements

Labels should be dynamic through an API similar to messages in case they need to change for multiple-language/I18N support. They are a bit different from messages because they necessarily correspond to a schema key and are not related to error type, whereas messages can be custom per key but need not be and are necessarily related to error type.

The plan: define in schema, as now, but allow them to be changed at any time with a labels method.

Also add label inflection from property names. This would help with the simple English-only cases where you're just capitalizing the first letter or whatnot. Inflection can be done when the schema object is initially parsed in the constructor function. If label is not defined, define it automatically using inflection. Other areas of the code can then be streamlined to assume label will always be set rather than falling back to the property name.

Probably use _.humanize from underscore.string.

Embrace the Meteor Match API

Currently type can be a JavaScript object like String, an object constructor like Date or any of those wrapped in brackets like [String].

This is a strict subset of what the Meteor Match API propose.

It would be nice to accept every Match pattern.

Performance Improvement for Clean and Validate Workflow

Right now collection2 and probably most other use cases do this:

//clean up doc
doc = schema.filter(doc);
doc = schema.autoTypeConvert(doc);
//validate doc
schema.validate(doc);

For a client-side insert or update, this happens twice in the collection2 pkg. Each of those functions is doing some kind of looping over either the doc object or the schema object. With some significant rewriting, it should be possible to change the API to the following and gain some efficiency:

doc = schema.validate(doc, {
  filter: true,
  typeConvert: true
});

For sure, the filter() and autoTypeConvert() functions can be combined and called from validate() based on options passed in. And since validate() currently does not return anything, it can then return the modified doc.

Some further combination with the validation loop may be possible, but I think there will need to be two loops no matter what because it needs to check both that no required fields are missing and also that no extra fields are present.

Embedded Documents

How would I go about embedding documents in a collection? Like embedding comments into a post?

Validate API is confusing

If find this API confusing:

MySchema.validate(obj); // return undefined
MySchema.valid(); // reactive bool

How can I validate more than one reactive object? (imagine a html table where each line is a element from a collection, and at the end of the line a indicator that show if the line is correct, same model for all the lines, different objects)

Any thoughts on it?

validating objects fails when setting as object

My app is breaking with a recent update to simple-schema and collection2. I have tracked it down to the following case:

var ss = new SimpleSchema({
  'foo.bar': { type: Number }
});

var ctx = ss.newContext();

ctx.validate({$set: { 'foo.bar': 29 }}, { modifier: true });  // works
console.log(ctx.invalidKeys());
// prints: []

ctx.validate({$set: { foo: {bar : 30 }}}, { modifier: true });  // doesn't work, but should?
console.log(ctx.invalidKeys());
// prints: [ { name: 'foo.$.bar',
//             type: 'keyNotInSchema',
//             message: 'foo.$.bar is not allowed by the schema' } ]

My app is using collection2, and doing Collection.update({_id: whatever}, {$set: {foo: someobj}}) which worked before, but now fails as in the example above. foo.bar is not an array, so the error is incorrect.

Problem with array validation

Hi there,

first of all, I would like to express a big Thank You to you for investing the time to create and maintain the simple-schema, collection2 and autoform packages. They are very helpful to me!

Today, however, I experienced an odd issue with array validation. My collection definition and insertion look like the following:

StudiesSmartCollection = new Meteor.SmartCollection 'studies'
@Studies = new Meteor.Collection2 StudiesSmartCollection,
    schema:
        'name':
            label: "study name"
            type: String
        'researchers':
            label: "researchers"
            type: [Object]
            minCount: 1
        'researchers.$._id':
            label: "researcher's ID"
            type: String
        'researchers.$.role':
            label: "researcher's role"
            type: String
            allowedValues: allowedStudyRoleValues

newStudyId = Studies.insert
    name: 'Give-me-a-name study'
    researchers: [
        {
            '_id': Meteor.user()._id
            'role': "creator"
        }
    ]

I am getting the following error trace in the client console:

insert failed: Error: failed validation
    at _.extend._insertOrUpdate (http://localhost:3000/packages/collection2.js?dd6c26f37df1d4741e85f32967cc7f36d5ce8ca2:186:21)
    at _.extend.insert (http://localhost:3000/packages/collection2.js?dd6c26f37df1d4741e85f32967cc7f36d5ce8ca2:196:21)
    at Object.Template.studies.events.click .bd-create-study (http://localhost:3000/studies/main.coffee.js?6f62ebfa8370124f8bc9e97ad5f895778c5e72ba:87:28)
    at Object.<anonymous> (http://localhost:3000/packages/templating.js?05b762a6c16769651cfe346f68018b47eacac716:196:32)
    at Spark.attachEvents._renderer.annotate.range.handler (http://localhost:3000/packages/spark.js?c9939ae1b11c764e0ce2709f852e72f6382467e6:878:38)
    at http://localhost:3000/packages/spark.js?c9939ae1b11c764e0ce2709f852e72f6382467e6:775:11
    at Array.forEach (native)
    at Function._.each._.forEach (http://localhost:3000/packages/underscore.js?a1286cdb983623d4d035c8d7cd7a1e8e15274cf5:130:11)
    at http://localhost:3000/packages/spark.js?c9939ae1b11c764e0ce2709f852e72f6382467e6:774:9
    at http://localhost:3000/packages/universal-events.js?5bfa39513d2caa4af4f829d7f4907afae3601adf:143:26 

Printing the invalid keys to the console (using Studies.simpleSchema().invalidKeys()), yields the following output:

invalid key 1: Object {name: "researchers.$._id", type: "required", message: "researcher's ID is required"}
invalid key 2: Object {name: "researchers.$.role", type: "required", message: "researcher's role is required"}

Adding an attribute optional: true to the fields researchers.$._id and researchers.$.role seems to suppress the error from being thrown and the fields are correctly inserted into the database. However, I would like to make them required fields. Am I missing an important detail here or is that a bug that needs to be fixed?

Cheers,
Mike

Allowing custom properties

What do you think of allowing custom properties to let other packages have the possibility to enhance the Simple Schema with additional information? As an example:

var schema = new SimpleSchema({
    'image' : {
        'type' : String,
        'otherPackage' : {
            'animated' : true
        }
    }
});

I'd also be okay with only one property called "custom" or something where one can define such informations.

Faulty ruleset when reusing objects with Array types

With the creation of a SimpleSchema the used object may be altered causing any creation of SimpleSchema's using the same object to contain a faulty ruleset.

for example:

var example = {
    something: {
        label: 'something',
        type: [String]
    }
}

var schema = new SimpleSchema(example);

now when logging the original example object you'll get this:

{
    "something": {
        "label": "something"
    },
    "something.$": {
        "label": "something",
        "optional":true
    }
} 

I'm guessing this is used by SimpleSchema to handle Arrays as type.

The issue I encountered was when I later reusing this example object (and adding some new fields) that the something.$ was still present.

With this new ruleset the SimpleSchema will no longer accept an Array of strings.

// reusing the example variable
var otherSchema = new SimpleSchema(example);

var valid = otherSchema.newContext().validate({ 
    something: ['hello', 'world'] 
});

valid will be false and the following errors will be present:

[
    { 
        name: 'something.0',
        type: 'keyNotInSchema',
        message: 'something.0 is not allowed by the schema' 
    },
    { 
        name: 'something.1',
        type: 'keyNotInSchema',
        message: 'something.1 is not allowed by the schema' 
    }
]

Now I don't know if this is something known or something that should be fixed. It's something I came across and you should probably be vigilant for.

getNativeStringProperties crashes on Firefox 26

Hi,

I don't know yet, if this is triggered by a misconfiguration in my Schemas, but getNativeStringProperties (strings.js:582) crashes in my browser , as the try - catch - Block is probably not working as intended.

//...
      var func = __nsp[name];
      try {
        var type = typeof func.apply('teststring', []);
        retObj[name] = type;
      } catch (e) {}
//...

Apparently func can be undefined in this situation. As a safeguard i added an if - clause around it, which works for me. But I'm not really sure, if this is the correct approach, as I don't understand the module and the implications of this change (yet).

//...
      var func = __nsp[name];
      if (func) {
        try {
          var type = typeof func.apply('teststring', []);
          retObj[name] = type;
        } catch (e) {}
     }
//...

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.