geddy / model Goto Github PK
View Code? Open in Web Editor NEWDatastore-agnostic ORM in JavaScript
Datastore-agnostic ORM in JavaScript
User creation fails when using 3rd-party auth (geddy-passport) and auto-incrementing IDs.
error: invalid input syntax for integer: "undefined"
Wondering you're interested in adding support for removal via queries as well as ids
This was probably hidden because I broke the memory tests that are in front of them, but yeerp they're broken on mongo and postgres since 15c506d.
Let's say I have Model A with A.hasOne('B');
Now I do:
b_foo = model.B.create();
// asume we saved b_foo now
b_bar = model.B.create();
// asume we saved b_bar now
a_foo = model.A.create();
a_foo.setB(b_foo);
a_foo.save();
// b_foo now has the foreign key for a_foo set in the DB
a_foo.setB(b_bar);
a_foo.save();
// b_foo and b_bar now have both the foreign key set for a_foo in the DB
// however b_foo should have an empty foreign key for a_foo instead
It loads JSON as strings even if the datatype of the property is 'object'.
With the example User class and a mongo adapter, if after registering the model I do User.first()
I get an error:
TypeError: Cannot call method 'find' of undefined
at Cursor._resolve (/home/me/project/node_modules/mongodb-wrapper/lib/Cursor.js:54:35)
at Cursor.resolve (/home/me/project/node_modules/mongodb-wrapper/lib/Cursor.js:43:24)
at Cursor.g (events.js:192:14)
at Cursor.EventEmitter.emit (events.js:93:17)
at Collection.Cursor.resolve._this (/home/me/project/node_modules/mongodb-wrapper/lib/Cursor.js:30:24)
at Collection.g (events.js:192:14)
at Collection.EventEmitter.emit (events.js:93:17)
at Collection.isOpen (/home/me/project/node_modules/mongodb-wrapper/lib/Collection.js:38:17)
at Db.collection (/home/me/project/node_modules/mongodb-wrapper/node_modules/mongodb/lib/mongodb/db.js:478:44)
at EventEmitter.Collection.isOpen (/home/me/project/node_modules/mongodb-wrapper/lib/Collection.js:33:27
This happens even if there are things in the users collection. It does not happen if I do the same find
call in the callback of a save operation.
Why can't I search right away?
Test script source:
var model = require('model');
var User = function () {
this.adapter('mongo', {})
this.property('login', 'string', {required: true});
this.property('password', 'string', {required: true});
this.property('lastName', 'string');
this.property('firstName', 'string');
this.validatesPresent('login');
this.validatesFormat('login', /[a-z]+/, {message: 'Subdivisions!'});
this.validatesLength('login', {min: 3});
this.validatesConfirmed('password', 'confirmPassword');
this.validatesWithFunction('password', function (s) {
// Something that returns true or false
return s.length > 0;
});
// Can define methods for instances like this
this.someMethod = function () {
// Do some stuff
};
};
// Can also define them on the prototype
User.prototype.someOtherMethod = function () {
// Do some other stuff
};
User = model.register('User', User);
/*
var u = User.create({
'login': 'test',
'password': 'secret',
'confirmPassword': 'secret'
});
if (u.isValid()) {
u.save(function(err, data) {
if (err) {
throw err;
}
console.log("new item saved");
*/
User.first(function(err, data) {
console.log(arguments);
});
/*
});
} else {
console.log("user invalid");
}
*/
application.coffee:
Application = ->
@defineProperties
name:
type: "string"
required: true
process_count:
type: "number"
required: true
controller:
app = geddy.model.Application.create name: "blah"
app.updateProperties process_count: 6
app.save (err, data) =>
if err
geddy.log.error util.inspect(err) # <== "process_count" is required.
Problem appers to be in validateAndUpdateFromParams method which converts property name to camel case and than tries to validate it with uncoverted params object.
Using the scaffold or model generator to generate a property type of text, results in a model with a type of string:
geddy model comment title:default:string body:text
generates a model that looks like this
var Comment = function () {
this.defineProperties({
title: {type: 'string', required: true},
body: {type: 'string'},
});
};
Note also the unnecessary trailing comma on the last property. I've tried all the listed datatypes, this is the only one that gets rewriiten.
I thought this might have crept in because MongoDB, unlike PostgreSQL, doesn't support the text datatype.
Using Geddy 0.6.19 and Model 0.0.25
Useful for something like a Contact model with a validatable 'email' field.
If I do:
geddy.model.Item.on('save', function (data) {
// do shit
});
I expect data to be the data for the thing that was saved (with {saved: true, id: blah, etc.}
.
I'll look into this one, but I wanted @mde's thoughts on this one.
I was looking at things that some other frameworks do, and some of these seemed nice. I wasn't sure if Model handled uniqueness or not yet.
User.validatesInclusion('gender', {in: ['male', 'female']});
User.validatesExclusion('domain', {in: ['www', 'billing', 'admin']});
User.validatesNumericality('age', {int: true});
User.validatesUniqueness('email', {message: 'email is not unique'});
There should be a way define a sort order for relations as this is a very common requirement.
e.g. User.getTweets
should return its requests in chronological order
Make this work:
var Item = function () {
this.defineProperties({
name: {type: 'string'}
});
this.findByName = function (name, callback) {
geddy.model.Item.all({name: name}, callback);
}
}
Item.findByName = function (name, callback) {
geddy.model.Item.all({name: name}, callback);
// would this work?
// this.all({name: name}, callback);
}
A way to set this directly in the definition. Would need to make sure this is a valid value according to the definition.
HI,
I looked through some samples but could not find the following two things:
An entity (Person) can have a property (Name) but how does the adapter knows, how the underlying columnis called? It could be called "name" for sure, but in more complex scenarios, the database might use column names like "max_login_retries" whereas the property is spelled maxLoginRetries. So how can I specify the underlying column?
An entity like "User" can have a NavigationProperty like getAccounts(). But how does the underlying adapter know, which field on the User-table is responsible for mapping? And how do you specify m:n relationships and especially the mapping table and it's columns? The mapping_table could be for example "user_account" with columns "user_id" and "account_id" or just a view named view_user_account.
I hope I did not ignore some facts or overlooked documentation somewhere.
This would make it safer to update attributes from arbitrary sources like request parameters without explicit removal of harmful attributes.
I have a username field and want to validate that the value entered is unique. It doesn't look like a validator exists for this (why not? seems a common requirement) so I was trying to write one with validatesWithFunction. But to check if it's unique I have to query the data store, and the only method to do this is asynchronous. I'm new to node and can't figure out how to get the result of the query and return it to the validation function.
Right now I have (coffee):
@property 'username', 'string'
required: true
@validatesWithFunction 'username', (val) ->
User.first username: val, (err, data) ->
throw err if err
data?
, message: "Username must be unique"
But obviously I'm not returning whether data exists to anywhere useful and meanwhile the validation function has already exited.
I must be missing something -- please point me in the right direction.
Docs say registerModel, source code says just register.
For example:
this.validatesLength("prop", { min: "1", max: "3" });
If we use a string instead of a number �it's simply ignored, which makes it hard to debug. If we threw instead it would be clearer.
validatesFormat might have a similar problem if the regEx is missing.
Simple test case:
, 'test all, using less-than createdAt on offset date': function (next) {
Zooby.all({createdAt: {lt: utils.date.add(new Date(), 'day', -1)}},
{}, function (err, data) {
assert.equal(data.length, 0);
if (err) {
throw err;
}
next();
});
}
Discussion: https://groups.google.com/forum/?hl=en#!topic/geddyjs/Qh5EQPkdtfA
"Or" query with simple equality fails with "id" property in both Mongo and memory adapters.
This is done, but needs tests.
In summary, it will look like this:
this.hasMany('Contributors', {model: 'Users'});
And
this.belongsTo('Owner', {model: 'User'});
Hi,
I noticed that there is an issue in functions insert and update on mongo adapter in lines 240 and 309.
As I noticed the variable 'model' is not declared anywhere. I checked with other adapters and you just forgot to include model = require('../../index') at the begining of the file.
The same for postgres
'Limit' is implemented in Postgres only, and there are no tests for limit in the shared adapter tests.
Validation errors are getting masked, so the process dies with no visible error
Related: geddy/geddy#240
Is there any way to use the like comparison to match any part of a string, not just the beginning?
Right now I believe that the mongo adapter doesn't allow to execute a runcommand on the model collection such as 'geddy.model.Mymodel.runcommand'.
The runcommand is used for example in the new Text Search feature of Mongo 2.4.
Saw in this thread of the group https://groups.google.com/forum/?fromgroups=#!topic/geddyjs/4-lOolZPApE
The error comes in this line https://github.com/mde/model/blob/master/lib/validators.js#L36 when 'val' is 0 then the expression '!val' evaluates to 'true'. We should check that the typeof val is undefined.
Fix is coming soon.
Sort with skip and limit option is not working. It brings all the data on the table. Please refer code below.
var sortData = {
id: 'asc',
title: 'asc',
status: 'asc',
createdAt: 'asc'
}
geddy.model.Todo.all({}, {sort:sortData}, { skip: 0, limit: geddy.config.pagelimit }, function (err, todos) {
console.log(err);
self.respond({ params: params, todos: todos });
});
The mongo adapter looks for mongodb-wrapper installed locally in the app. We need to be able to specify somehow the version we need.
Check for "not empty string, not null, not undefined" is being done inline in multiple places. Make this all one single function call.
Sort with multiple column is not working. It sorts only the first column.
var sortData = {
id: 'asc',
title: 'desc',
status: 'asc',
createdAt: 'asc'
}
geddy.model.Todo.all({}, {sort:sortData}, function (err, todos) {
console.log(err);
self.respond({ params: params, todos: todos });
});
Using geddy, set up the following:
this.getMyThings = function (req, resp, params) {
var self = this;
geddy.model.User.first(self.session.get('userId'), function(err, user) {
user.getThings(function(err,things){
self.respond({params: params, things: things});
});
});
};
To diagnose, Add the following snippet to https://github.com/mde/model/blob/master/lib/query/query.js#L111
console.log("Looking for "+key + " on ");
console.log(model.descriptionRegistry[
this.model.modelName].properties)
You'll notice that it's trying to look for the wrong key on the wrong model.
Model looks like a welcome addition to the JS ORM world, thanks.
I can't see any mention of the ability to create indexes, is that planned?
Are you considering implementing Model for use in the Browser with IndexedDB and WebSQL?
-Neville
I'm refering to this line: https://github.com/mde/model/blob/master/lib/index.js#L1048
It's already stated in the comment above that this method needs to be fired after a allModelsRegistered event or such. My very dirty hack was to set the timeout ot 1000. This works almost all the time but is not desirable of course. However I'm not understanding the full complexity of the model code at all and thus cannot provide a good solution.
it would be super rad if this supported the Stream api for large reads/writes. i like this API quite a lot https://github.com/rvagg/node-levelup#api
In the model docs it says I can do:
this.defineProperties({
foo: {type: 'array', required: true}
});
In my controller (create()
) I have:
foo.save(function (err, data) {
var fooId = data.id;
bar.foos = [fooId];
if (bar.isValid()) {
bar.save(/* ... */);
}
});
But it throws a 500
Error: 500 Internal Server Error
TypeError: Cannot read property 'validate' of undefined
at Object.utils.mixin.validateProperty (/usr/local/lib/node_modules/geddy/node_modules/model/lib/index.js:844:57)
at Object.utils.mixin.validateAndUpdateFromParams (/usr/local/lib/node_modules/geddy/node_modules/model/lib/index.js:804:24)
at Object.utils.mixin.createItem (/usr/local/lib/node_modules/geddy/node_modules/model/lib/index.js:717:17)
at Function.obj.create (/usr/local/lib/node_modules/geddy/node_modules/model/lib/index.js:444:31)
at create (/Users/oscar/Dropbox/projects/APP/app/controllers/users.js:26:33)
at callback [as last] (/usr/local/lib/node_modules/geddy/lib/controller/base_controller.js:349:22)
at async.AsyncBase.next (/usr/local/lib/node_modules/geddy/node_modules/utilities/lib/async.js:116:12)
at controller.BaseController._execFilters (/usr/local/lib/node_modules/geddy/lib/controller/base_controller.js:197:11)
at controller.BaseController._handleAction (/usr/local/lib/node_modules/geddy/lib/controller/base_controller.js:359:20)
at cb [as callback] (/usr/local/lib/node_modules/geddy/lib/app/index.js:279:36)
Simply changing it to a "string" type and changing bar.foos = [fooId];
to bar.foos = fooId;
makes it work.
cc: @dadambickford
User.first(undefined, callback); => Should first be callable without a valid search param?
Model.findOrCreate({foo: bar}, fn)
should find the first record matching the query params, or if none found create a new, unsaved record like create(params)
, same as Rails’ find_or_initialize_by
Implement single-table inheritance: http://www.martinfowler.com/eaaCatalog/singleTableInheritance.html
Done but needs tests.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.