I'm trying to create an array of objects using simple-schema. In this example, a person has a careerHistory object that is filled with individual positions. I can't figure out how to insert and update the array of objects. It just errors. The only way I can get it to work is to be explicit, eg. 'careerHistory.position.1.company'.
I'm using:
meteor
simple-schema
reactjs
collection2-core
Path: mongodb
const ProfileCandidateSchema = new SimpleSchema({
userId: {
type: String,
regEx: SimpleSchema.RegEx.Id
},
careerHistory: { type: Array, optional: true },
'careerHistory.position': { type: Object, optional: true },
'careerHistory.position.$': { type: Object, optional: true },
'careerHistory.position.$.company': { type: String, optional: true },
'careerHistory.position.$.title': { type: String, optional: true }
});
Path: updateForm.js
ProfileCandidate.update(id, { $set: {
'careerHistory.position.company': this.state['position.company'],
'careerHistory.position.title': this.state['position.title'],
}
});
If you want to push object to array do
ProfileCandidate.update(id,
{ $push: { careerHistory: { position: {
'company': this.state['position.company'],
'title': this.state['position.title'],
}}}
});
if you want to update particular object
ProfileCandidate.update({ _id: id, 'careerHistory.position.company': this.state['position.company'] }, { $set: {
'careerHistory.position.$.title': this.state['position.title'],
}
});
see $ in set
Related
Please tell me what I'm missing here. When I update the Array of objects my collection updates with an empty array. I'm using meteor-collection2-core and node-simple-schema.
Path: Method
testArray = [{
"institution": "Swinburn",
"uniqueId": 1501036480813,
"qualification": "Bachelor of Commerce",
"completed": "2017"
}]
ProfileCandidate.update('Ntzj6kE8qZsvSPMEP', {$set: {educationQualifications: testArray}});
Path: Collection
export const ProfileCandidate = new Mongo.Collection('profileCandidate');
const ProfileCandidateSchema = new SimpleSchema({
userId: {
type: String,
regEx: SimpleSchema.RegEx.Id
},
educationQualifications: { type: Array, optional: true },
'educationQualifications.$': { type: Object, optional: true },
'educationQualifications.$.uniqueId': { type: Number, optional: true },
'educationQualifications.$.institution': { type: String, optional: true },
'educationQualifications.$.qualification': { type: String, optional: true },
'educationQualifications.$.completed': { type: String, optional: true }
});
ProfileCandidate.attachSchema(ProfileCandidateSchema);
In your method, try this:
ProfileCandidate.update({userId: 'Ntzj6kE8qZsvSPMEP'}, {$set: {educationQualifications: testArray}});
I'm struggling to figure out how to make password validation with my user Schema, that's how I've being doing so far:
This is the schema:
Schema = {};
Schema.UserProfile = new SimpleSchema({
//LOTS OF FIELDS WORKING FINE
});
Schema.User = new SimpleSchema({
username: {
type: String,
optional: true
},
emails: {
type: Array,
},
"emails.$": {
type: Object
},
"emails.$.address": {
type: String,
regEx: SimpleSchema.RegEx.Email
},
"emails.$.verified": {
type: Boolean
},
createdAt: {
type: Date
},
profile: {
type: Schema.UserProfile,
label: "Perfil",
optional: false
},
services: {
type: Object,
blackbox: true
},
"services.$": {
type: Object,
blackbox: true
},
"services.$.password": { // IS IT RIGHT?
type: String,
label: "Senha",
min: 8
},
roles: {
type: String,
optional: true
}
});
Meteor.users.attachSchema(Schema.User);
And this is how I'm saving:
let company = {};
company = {
email: $('#email').val(),
password: $('#password').val(),
roles: 'company',
profile: companyProfile
}
Meteor.call('saveUser', company, function(error, result) {
if ( error ) {
console.log(error);
}
}
Meteor.methods({
saveUser: function(data) {
return Accounts.createUser(data);
}
});
I'm still a beginner, so I'm probably messing something up here. When I try to create the user, if there is an issue with any of the fields, the validation throws an error as expected. However no error is thrown in case I miss the password, any ideas of what I'm doing wrong here?
------------------------------- UPDATE ----------------------------------
Thanks #aedm for your answer. I really wish I could have something like this to verify the password and password confirmation:
password: {
type: String,
label: "Senha",
min: 8
},
password_confirmation: {
type: String,
label: "Confirmação de Senha",
min: 8,
custom: function () {
if (this.value !== this.field('password').value) {
return "passwordMismatch";
}
}
},
I guess it's not possible then, is it?
Meteor only stores a bcrypt hash for the password, it's always longer than 8 characters.
Instead, your saveUser method should throw an error when the password criteria isn't met.
Meteor.methods({
saveUser: function(data) {
if (data.password.length < 8) throw new Meteor.Error("Password too short");
return Accounts.createUser(data);
}
});
I'd try to avoid defining a schema for users, Meteor handles it pretty well without one, and it's not trivial how to do it properly.
I have an app in which I'm using a template helper. I have the following code:
UI.registerHelper('ProfileNameByUserId', function(userid) {
console.log('Userid: ' + userid);
var user = Meteor.users.findOne({'_id': userid});
console.log.log('User:' + user);
return user.username
});
I'm calling this in my template as follows:
{{#each getDocuments}}
{{ProfileNameByUserId userid}}
{{/each}}
and in the template helper:
Template.documentsIndex.helpers({
getDocuments: function () {
return Documents.find({}, { sort: { createdAt: -1 }});
}
});
The publish and subscribe are as follows:
Routes.route('/documents', {
name: 'documents',
subscriptions: function (params, queryParams) {
this.register('documentsIndex', Meteor.subscribe('documents'));
},
action: function (params, queryParams) {
.....
});
}
});
Meteor.publish('documents', function () {
return Documents.find({})
});
I'm sure the userId is passed on, as a console.log statement shows the correct id. The issue is that the user is 'undefined' so it can't find the username.
I'm using SimpleSchema to define a users schema which looks as follows:
Users = Meteor.users;
Schema = {};
Schema.UserProfile = new SimpleSchema({
firstName: {
type: String,
optional: true
},
lastName: {
type: String,
optional: true
},
gender: {
type: String,
allowedValues: ['Male', 'Female'],
optional: true
},
});
Schema.User = new SimpleSchema({
username: {
type: String,
optional: true
},
emails: {
type: Array,
optional: true
},
"emails.$": {
type: Object
},
"emails.$.address": {
type: String,
regEx: SimpleSchema.RegEx.Email
},
"emails.$.verified": {
type: Boolean
},
createdAt: {
type: Date,
optional: true,
denyUpdate: true,
autoValue: function() {
if (this.isInsert) {
return new Date();
}
}
},
profile: {
type: Schema.UserProfile,
optional: true
},
services: {
type: Object,
optional: true,
blackbox: true
},
roles: {
type: [String],
optional: true
}
});
Meteor.users.attachSchema(Schema.User);
});
Replacing Meteor.users.findOne() in the template helper with Users.findOne() does not work either.
Any idea why user remains undefined?
You need to add a publication and subscription for the users that you want to show.
In the most general case in which all users are published:
Meteor.publish('allUsers', function () {
return Meteor.users.find();
});
Subscribe to this in your route and you will not have the user undefined in your helper.
Note that you should only publish the users that you need, but since I do not know you application structure I cannot give you a query for that.
I'm having some trouble with updating a user account. I use the following schema (collection2):
lib/collections/users.js
Users = Meteor.users;
var Schemas = {};
Schemas.User = new SimpleSchema({
gender: {
type: Number,
min: 1
},
s_gender: {
type: Number,
min: 1,
optional:false
},
picture: {
type: String,
custom: function() {
var base64Matcher = new RegExp("^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{4})$");
var value = this.value.replace("data:image/png;base64,","");
if(!base64Matcher.test(value))
{
return 'no picture';
}
else
{
return true;
}
}
}
});
Users.attachSchema(Schemas.User);
Now I do the update with the following code:
client/templates/start.js
Users.update({_id: Meteor.userId()}, {
$set: {picture: picture, gender: gender, s_gender: s_gender}
}, {validationContext: "updateUser"}, function (error, result) {
if (error) {
errorObjs = Users.simpleSchema().namedContext("updateUser").invalidKeys();
console.log(errorObjs);
}
console.log(result);
});
The validation passes, but I only get a "0" in results (errors are null) - the update isn't working. Errors are shown if I have an empty field, so the validation is working well. If I detach the schema, the update works fine.
Did I forget something here or why isn't he updating when validation passes?
// Edit: Also I see, that Meteor doesn't create users anymore.
I believe you need to use Users.profile.foo instead of Users.foo, because Users is a special meteor collection and you can only save new fields inside the profile field. Try using Simple Schema/Collection 2 suggested User schema as a starting point (I'll copy it bellow). Notice the "profile schema" is loaded before the user schema:
Schema = {};
Schema.UserProfile = new SimpleSchema({
firstName: {
type: String,
regEx: /^[a-zA-Z-]{2,25}$/,
optional: true
},
lastName: {
type: String,
regEx: /^[a-zA-Z]{2,25}$/,
optional: true
},
birthday: {
type: Date,
optional: true
},
gender: {
type: String,
allowedValues: ['Male', 'Female'],
optional: true
},
organization : {
type: String,
regEx: /^[a-z0-9A-z .]{3,30}$/,
optional: true
},
website: {
type: String,
regEx: SimpleSchema.RegEx.Url,
optional: true
},
bio: {
type: String,
optional: true
}
});
Schema.User = new SimpleSchema({
username: {
type: String,
regEx: /^[a-z0-9A-Z_]{3,15}$/
},
emails: {
type: [Object],
optional: true
},
"emails.$.address": {
type: String,
regEx: SimpleSchema.RegEx.Email
},
"emails.$.verified": {
type: Boolean
},
createdAt: {
type: Date
},
profile: {
type: Schema.UserProfile,
optional: true
},
services: {
type: Object,
optional: true,
blackbox: true
}
});
Meteor.users.attachSchema(Schema.User);
source: https://github.com/aldeed/meteor-collection2
This works and insert {name: 'ok', color: '#ff0000'} to the categories when using Robomongo
db.requirements.update({_id: 'kJBZp2gA8TgNX3z2j'}, {$addToSet: {categories: {name: 'ok', color: '#ff0000'}}})
It does not from Meteor.
It inserts an empty object {} into categories array
EDIT
After SimpleSchema.debug = true; I have this log:
SimpleSchema.clean: filtered out value that would have affected key
"categories.$._id", which is not allowed by the schema
same for name and color thus inserting an empty object {}
The schema is:
categories: {
type: [{
_id: {
type: String
},
name: {
type: String
},
color: {
type: String
}
}],
optional: true
}
What would be the correct schema then ?
I don't grasp all the differences, but here is the new schema that now works. Thanks Matt K for the debug option pointer.
'categories.$._id': {
type: String,
optional: true
},
'categories.$.name': {
type: String,
optional: true
},
'categories.$.color': {
type: String,
optional: true
},