Avoiding global leaking when using JayData 1.3.4 local item store - jaydata

Out of the box Entities defined by using $data.Entity.extend will be globally accessible. e.g. in the example taken from JayData's home page Todo will leak.
// Case 1: local item store example from http://jaydata.org/
$data.Entity.extend("Todo", {
Id: { type: "int", key: true, computed: true },
Task: { type: String, required: true, maxLength: 200 },
DueDate: { type: Date },
Completed: { type: Boolean }
});
console.log('Leaks Todo?', typeof window.Todo !== 'undefined');
//Result: true
In a JayData forum post I found a reference to $data.createContainer(), which can be used as container during Entity definition. In this case Todo2 won't leak.
// Case2: creating Todo2 in a container
$data.Entity.extend("Todo2", container, {
Id: { type: "int", key: true, computed: true },
Task: { type: String, required: true, maxLength: 200 },
DueDate: { type: Date },
Completed: { type: Boolean }
});
console.log('Leaks Todo2?', typeof window.Todo2 !== 'undefined');
//Result: false
Unfortunately after accessing stores there'll be other variables that leak globally even if the Entity itself is associated with a container.
console.log('Before store access: Leaks Todo2_items?',
typeof window.Todo2_items !== 'undefined');
//Result: false
$data('Todo2').save({ Task: 'Initialized Todo2'})
console.log('After store access: Leaks Todo2_items?',
typeof window.Todo2_items !== 'undefined');
//Result: true
Complete fiddle can be found at http://jsfiddle.net/RainerAtSpirit/nXaYn/.
In an ideal world every variable that is created for entities that run in a container would be associated with the same container. Is there an option to accomplish that or is the behavior described in Case2 the best that can be currently accomplished?

Related

Global Models in SailsJS not accessible

In porting a sails app to 1.x framework. I found that my global model names (which are physically defined in api/models directory) were undefined in one of my hook initialize function and in config/bootstrap.js
"models": true, is defined in config/globals.js in this project.
For example, one of my models is Job.js:
const async = require('async');
const _ = require('lodash');
const fetch = require('node-fetch');
module.exports = {
attributes: {
id: {
type: 'integer',
autoIncrement: false,
unique: true,
primaryKey: true
}
},
Init: function(params,cb) {
sails.log.info('Job Engine Starting');
...
}
}
But, when I try to call Job.Init(), from hooks/index.js or from config/bootstrap.js, I get reference error: Job is undefined.

Meteor - node simple schema validate data to match schema

I want to change my Rest-API validation to node simple schema for schema definition and collection2#core for schema validation.
I want to use the Person schema to validate the data provided by the users.
Schemas = {};
Schemas.Person = new SimpleSchema({
name: {
type: String,
label: "Person's Name",
unique: true,
max: 200
},
surname: {
type: String,
unique: true,
label: "person's surname"
},
};
validData = API.utility.validate(data, Schemas.Person });
API: {
utility: {
validate: function(data, schema) {
return "The SimpleSchema Validation";
}
}
};
This case is described in the simpl-schema documentation
With your schema definition you can just do:
Schemas.person.validate(data);
If right after that you want to look at the result or the errors:
Schemas.person.isValid();
Schemas.person.validationErrors();

ER_TOO_LONG_KEY in SailsJS 1.0 with sails-mysql

I got this error with sails when I try to sails lift:
info: ·• Auto-migrating... (drop)
error: A hook (`orm`) failed to load!
error:
error: Error: ER_TOO_LONG_KEY: Specified key was too long; max key length is 767 bytes
I just have one model for now: 
module.exports = {
datastore: 'default',
tableName: 'sci_user',
attributes: {
email: {
type: 'string',
required: true,
unique: true
},
password: {
type: 'string',
required: true
}
}
It's really simple and I got it from the documentation. I don't understand. It seems it's because of the unique: true.
This is due to a combination of factors, but the most pertinent one is that sails-mysql currently defaults to using the utf8mb4 character set for string attributes, to allow the use of emojis and other extended characters. We're working on a patch to make this configurable rather than the default, but in the meantime the quickest workaround is to declare the columnType for your attributes directly:
module.exports = {
datastore: 'default',
tableName: 'sci_user',
attributes: {
email: {
type: 'string',
required: true,
unique: true,
columnType: 'varchar'
},
password: {
type: 'string',
required: true,
columnType: 'varchar'
}
}

Typeahead/Bloodhound dupDetector for Multiple Datasets

I have two Bloodhound datasets, a local and a remote. The local data will always be duplicated in the remote results. I've found the dupDetector method mentioned in Typeahead documentation, but it seems this method only works if both my local and remote datasets are built within the same Bloodhound object.
Here's my code. Is there a way to filter duplicates across multiple Bloodhound datasets?
var local_props = new Bloodhound({
datumTokenizer: function (p) {
return Bloodhound.tokenizers.whitespace(p.name);
},
queryTokenizer: Bloodhound.tokenizers.whitespace,
local: portfolio_props,
limit: 100
});
var remote_props = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value'),
queryTokenizer: Bloodhound.tokenizers.whitespace,
remote: 'properties/searchPropertiesLike?substr=%QUERY',
dupDetector: function(remoteMatch, localMatch) {
return remoteMatch.name === localMatch.name;
},
limit: 100
});
local_props.initialize();
remote_props.initialize();
$('#typeahead-property').typeahead({
hint: true,
highlight: true,
minLength: 2
},
{
name: 'port_properties',
displayKey: 'name',
source: local_props.ttAdapter(),
templates: {
header: '<h3>Your Portfolio Properties</h3>'
}
},
{
name: 'dir_properties',
displayKey: 'name',
source: remote_props.ttAdapter(),
templates: {
header: '<h3>Properties Directory</h3>'
}
});

Sails.JS association validation

I'm using several one to many associations in Sails.JS that look like the following:
User
email: {
type: 'string',
required: true,
unique: true
},
projects: {
collection: 'project',
via: 'user'
}
Project
name: {
type: 'string',
required: true,
minLength: 3,
maxLength: 50
},
user: {
model: 'user',
required: true
},
sites: {
collection: 'site',
via: 'project'
}
Site
project: {
model: 'project',
required: true
},
name: {
type: 'string',
required: true
}
Now when I fire off a POST request to /project it creates the project fine, and specifying the param 'user' (taken from the session) associates the project with that particular user.
The same goes for when I create a new site. However, I appear to be able to specify any number for the param 'project', even if that particular project ID doesn't exist. Really it should fail the validation if the project doesn't exist and not create the site. I thought it'd look up the association with project and check that the project ID specified is valid?
Also, I only want to be able to create a site that is associated with a project that belongs to the current user. How would I go about doing this?
Thanks in advance.
I'm not sure if it's a bug or intended behavior with your non-existent project ID association, but one work-around is to have a beforeCreate hook in your models to verify that the project ID exists:
// In your Site model
beforeCreate: function(values, next) {
...
var projectID = values['project'];
Project.findOne(projectID, function (err, project) {
if (err || !project) return next("some error message");
return next();
});
}
You can also do a check in the beforeCreate hook for your second question:
// In your Site model
beforeCreate: function(values, next) {
...
var projectID = values['project'];
Project.findOne(projectID).populate('user').exec(function (err, project) {
if (err || !project) return next("some error message");
if (project.user.id != values['userID']) return next("some other error message");
return next();
});
}
Note that you'll have to pass 'userID' as a param into the params for creating a Site instance.