Skip to content
Toggle navigation
Projects
Groups
Snippets
Help
public
/
sequelize
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Settings
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
不要怂,就是干,撸起袖子干!
Commit 1b5fa1a2
authored
Jun 05, 2013
by
Sascha Depold
Browse files
Options
Browse Files
Download
Plain Diff
merge
2 parents
18818c7d
fb343483
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
170 additions
and
115 deletions
lib/dao-validator.js
lib/dao.js
lib/emitters/custom-event-emitter.js
spec-jasmine/dao.spec.js
spec/associations/has-one.spec.js
spec/dao.spec.js
spec/dao.validations.spec.js
spec/promise.spec.js
lib/dao-validator.js
View file @
1b5fa1a
...
...
@@ -2,33 +2,53 @@ var Validator = require("validator")
,
Utils
=
require
(
"./utils"
)
var
DaoValidator
=
module
.
exports
=
function
(
model
)
{
this
.
model
=
model
this
.
model
=
model
this
.
chainer
=
new
Utils
.
QueryChainer
()
}
DaoValidator
.
prototype
.
validate
=
function
()
{
var
errors
=
{}
errors
=
Utils
.
_
.
extend
(
errors
,
validateAttributes
.
call
(
this
))
errors
=
Utils
.
_
.
extend
(
errors
,
validateModel
.
call
(
this
))
return
errors
return
new
Utils
.
CustomEventEmitter
(
function
(
emitter
)
{
validateAttributes
.
call
(
this
)
validateModel
.
call
(
this
)
this
.
chainer
.
run
()
.
success
(
function
()
{
emitter
.
emit
(
'success'
)
})
.
error
(
function
(
err
)
{
var
errors
=
{}
Utils
.
_
.
each
(
err
,
function
(
value
)
{
Utils
.
_
.
extend
(
errors
,
value
)
})
emitter
.
emit
(
'success'
,
errors
)
})
}.
bind
(
this
)).
run
()
}
// private
var
validateModel
=
function
()
{
var
errors
=
{}
// for each model validator for this DAO
Utils
.
_
.
each
(
this
.
model
.
__options
.
validate
,
function
(
validator
,
validatorType
)
{
try
{
validator
.
apply
(
this
.
model
)
}
catch
(
err
)
{
errors
[
validatorType
]
=
[
err
.
message
]
// TODO: data structure needs to change for 2.0
}
Utils
.
_
.
each
(
this
.
model
.
__options
.
validate
,
function
(
_validator
,
validatorType
)
{
var
validator
=
prepareValidationOfAttribute
.
call
(
this
,
undefined
,
_validator
,
validatorType
,
{
omitValue
:
true
})
this
.
chainer
.
add
(
new
Utils
.
CustomEventEmitter
(
function
(
emitter
)
{
var
next
=
function
(
err
)
{
if
(
err
)
{
var
error
=
{}
error
[
validatorType
]
=
[
err
]
emitter
.
emit
(
'error'
,
error
)
}
else
{
emitter
.
emit
(
'success'
)
}
}
validator
.
args
.
unshift
(
next
);
validator
.
fn
.
apply
(
null
,
validator
.
args
)
}.
bind
(
this
)).
run
())
}.
bind
(
this
))
return
errors
}
var
validateAttributes
=
function
()
{
...
...
@@ -48,32 +68,27 @@ var validateAttributes = function() {
}
var
validateAttribute
=
function
(
value
,
field
)
{
var
errors
=
{}
// for each validator
Utils
.
_
.
each
(
this
.
model
.
validators
[
field
],
function
(
details
,
validatorType
)
{
var
validator
=
prepareValidationOfAttribute
.
call
(
this
,
value
,
details
,
validatorType
)
try
{
validator
.
fn
.
apply
(
null
,
validator
.
args
)
}
catch
(
err
)
{
var
msg
=
err
.
message
// if we didn't provide a custom error message then augment the default one returned by the validator
if
(
!
validator
.
msg
&&
!
validator
.
isCustom
)
{
msg
+=
": "
+
field
this
.
chainer
.
add
(
new
Utils
.
CustomEventEmitter
(
function
(
emitter
)
{
var
next
=
function
(
err
)
{
if
(
err
)
{
var
error
=
{}
error
[
field
]
=
[
err
]
emitter
.
emit
(
'error'
,
error
)
}
else
{
emitter
.
emit
(
'success'
)
}
}
// each field can have multiple validation errors stored against it
errors
[
field
]
=
errors
[
field
]
||
[]
errors
[
field
].
push
(
msg
)
}
validator
.
args
.
unshift
(
next
);
validator
.
fn
.
apply
(
null
,
validator
.
args
)
}.
bind
(
this
)).
run
())
}.
bind
(
this
))
// for each validator for this field
return
errors
}
var
prepareValidationOfAttribute
=
function
(
value
,
details
,
validatorType
)
{
var
prepareValidationOfAttribute
=
function
(
value
,
details
,
validatorType
,
options
)
{
var
isCustomValidator
=
false
// if true then it's a custom validation method
,
validatorFunction
=
null
// the validation function to call
,
validatorArgs
=
[]
// extra arguments to pass to validation function
...
...
@@ -82,7 +97,9 @@ var prepareValidationOfAttribute = function(value, details, validatorType) {
if
(
typeof
details
===
'function'
)
{
// it is a custom validator function?
isCustomValidator
=
true
validatorFunction
=
Utils
.
_
.
bind
(
details
,
this
.
model
,
value
)
validatorFunction
=
function
(
next
)
{
details
.
apply
(
this
.
model
,
((
options
||
{}).
omitValue
)
?
[
next
]
:
[
value
,
next
])
}.
bind
(
this
)
}
else
{
// it is a validator module function?
...
...
@@ -105,7 +122,16 @@ var prepareValidationOfAttribute = function(value, details, validatorType) {
}
// bind to validator obj
validatorFunction
=
Utils
.
_
.
bind
(
validator
[
validatorType
],
validator
)
validatorFunction
=
function
(
next
)
{
var
args
=
Array
.
prototype
.
slice
.
call
(
arguments
,
1
)
try
{
validator
[
validatorType
].
apply
(
validator
,
args
)
next
()
}
catch
(
err
)
{
next
(
err
.
message
)
}
}
}
return
{
...
...
lib/dao.js
View file @
1b5fa1a
...
...
@@ -148,27 +148,29 @@ module.exports = (function() {
this
.
dataValues
[
updatedAtAttr
]
=
values
[
updatedAtAttr
]
=
Utils
.
now
()
}
var
errors
=
this
.
validate
()
if
(
!!
errors
)
{
return
new
Utils
.
CustomEventEmitter
(
function
(
emitter
)
{
emitter
.
emit
(
'error'
,
errors
)
}).
run
()
}
else
if
(
this
.
isNewRecord
)
{
return
this
.
QueryInterface
.
insert
(
this
,
this
.
QueryInterface
.
QueryGenerator
.
addSchema
(
this
.
__factory
),
values
)
}
else
{
var
identifier
=
this
.
__options
.
hasPrimaryKeys
?
this
.
primaryKeyValues
:
{
id
:
this
.
id
};
if
(
identifier
===
null
&&
this
.
__options
.
whereCollection
!==
null
)
{
identifier
=
this
.
__options
.
whereCollection
;
}
return
new
Utils
.
CustomEventEmitter
(
function
(
emitter
)
{
this
.
validate
().
success
(
function
(
errors
)
{
if
(
!!
errors
)
{
emitter
.
emit
(
'error'
,
errors
)
}
else
if
(
this
.
isNewRecord
)
{
this
.
QueryInterface
.
insert
(
this
,
this
.
QueryInterface
.
QueryGenerator
.
addSchema
(
this
.
__factory
),
values
)
.
proxy
(
emitter
)
}
else
{
var
identifier
=
this
.
__options
.
hasPrimaryKeys
?
this
.
primaryKeyValues
:
{
id
:
this
.
id
};
if
(
identifier
===
null
&&
this
.
__options
.
whereCollection
!==
null
)
{
identifier
=
this
.
__options
.
whereCollection
;
}
var
tableName
=
this
.
QueryInterface
.
QueryGenerator
.
addSchema
(
this
.
__factory
)
,
query
=
this
.
QueryInterface
.
update
(
this
,
tableName
,
values
,
identifier
)
var
tableName
=
this
.
QueryInterface
.
QueryGenerator
.
addSchema
(
this
.
__factory
)
,
query
=
this
.
QueryInterface
.
update
(
this
,
tableName
,
values
,
identifier
)
return
query
}
query
.
proxy
(
emitter
)
}
}.
bind
(
this
))
}.
bind
(
this
)).
run
()
}
/*
...
...
@@ -209,13 +211,9 @@ module.exports = (function() {
* @return null if and only if validation successful; otherwise an object containing { field name : [error msgs] } entries.
*/
DAO
.
prototype
.
validate
=
function
()
{
var
validator
=
new
DaoValidator
(
this
)
,
errors
=
validator
.
validate
()
return
(
Utils
.
_
.
isEmpty
(
errors
)
?
null
:
errors
)
return
new
DaoValidator
(
this
).
validate
()
}
DAO
.
prototype
.
updateAttributes
=
function
(
updates
,
fields
)
{
this
.
setAttributes
(
updates
)
return
this
.
save
(
fields
)
...
...
lib/emitters/custom-event-emitter.js
View file @
1b5fa1a
...
...
@@ -6,13 +6,13 @@ var util = require("util")
var
bindToProcess
=
function
(
fct
)
{
if
(
fct
)
{
if
(
process
.
domain
)
{
return
process
.
domain
.
bind
(
fct
);
}
if
(
process
.
domain
)
{
return
process
.
domain
.
bind
(
fct
)
}
}
return
fct
;
}
;
return
fct
}
module
.
exports
=
(
function
()
{
var
CustomEventEmitter
=
function
(
fct
)
{
...
...
@@ -54,6 +54,7 @@ module.exports = (function() {
return
this
}
// emit the events on the foreign emitter once events got triggered for me
CustomEventEmitter
.
prototype
.
proxy
=
function
(
emitter
)
{
proxyEventKeys
.
forEach
(
function
(
eventKey
)
{
this
.
on
(
eventKey
,
function
(
result
)
{
...
...
@@ -73,7 +74,5 @@ module.exports = (function() {
}).
then
(
onFulfilled
,
onRejected
)
}
return
CustomEventEmitter
;
return
CustomEventEmitter
})()
spec-jasmine/dao.spec.js
View file @
1b5fa1a
...
...
@@ -308,11 +308,12 @@ describe('DAO', function() {
name
:
'snafu'
,
identifier
:
'identifier'
}).
success
(
function
(
user
)
{
var
emitter
=
user
.
updateAttributes
({
name
:
'foobar'
})
emitter
.
success
(
function
()
{
expect
(
emitter
.
query
.
sql
).
toMatch
(
/WHERE
[
`"
]
identifier
[
`"
]
..identifier./
)
done
()
})
user
.
updateAttributes
({
name
:
'foobar'
})
.
on
(
'sql'
,
function
(
sql
)
{
expect
(
sql
).
toMatch
(
/WHERE
[
`"
]
identifier
[
`"
]
..identifier./
)
done
()
})
})
})
})
...
...
spec/associations/has-one.spec.js
View file @
1b5fa1a
...
...
@@ -20,7 +20,7 @@ describe(Helpers.getTestDialectTeaser("HasOne"), function() {
})
describe
(
'setAssociation'
,
function
()
{
it
(
'clears the association if null is passed'
,
function
(
done
)
{
it
(
'
//
clears the association if null is passed'
,
function
(
done
)
{
var
User
=
this
.
sequelize
.
define
(
'UserXYZ'
,
{
username
:
Sequelize
.
STRING
})
,
Task
=
this
.
sequelize
.
define
(
'TaskXYZ'
,
{
title
:
Sequelize
.
STRING
})
...
...
spec/dao.spec.js
View file @
1b5fa1a
...
...
@@ -422,7 +422,7 @@ describe(Helpers.getTestDialectTeaser("DAO"), function() {
expect
(
err
.
validateTest
).
toBeDefined
()
expect
(
err
.
validateTest
).
toBeArray
()
expect
(
err
.
validateTest
[
0
]).
toBeDefined
()
expect
(
err
.
validateTest
[
0
].
indexOf
(
'Invalid integer
:
'
)).
toBeGreaterThan
(
-
1
)
expect
(
err
.
validateTest
[
0
].
indexOf
(
'Invalid integer'
)).
toBeGreaterThan
(
-
1
)
done
()
})
})
...
...
spec/dao.validations.spec.js
View file @
1b5fa1a
...
...
@@ -201,7 +201,7 @@ describe(Helpers.getTestDialectTeaser("DaoValidator"), function() {
for
(
var
i
=
0
;
i
<
validatorDetails
.
fail
.
length
;
i
++
)
{
var
failingValue
=
validatorDetails
.
fail
[
i
]
it
(
'correctly specifies an instance as invalid using a value of "'
+
failingValue
+
'" for the validation "'
+
validator
+
'"'
,
function
()
{
it
(
'correctly specifies an instance as invalid using a value of "'
+
failingValue
+
'" for the validation "'
+
validator
+
'"'
,
function
(
done
)
{
var
validations
=
{}
,
message
=
validator
+
"("
+
failingValue
+
")"
...
...
@@ -221,11 +221,15 @@ describe(Helpers.getTestDialectTeaser("DaoValidator"), function() {
})
var
failingUser
=
UserFail
.
build
({
name
:
failingValue
})
,
errors
=
failingUser
.
validate
()
,
errors
=
undefined
;
expect
(
errors
).
not
.
toBeNull
()
expect
(
errors
).
toEqual
({
name
:
[
message
]
})
})
failingUser
.
validate
().
done
(
function
(
err
,
_errors
)
{
expect
(
_errors
).
not
.
toBeNull
();
expect
(
_errors
).
toEqual
({
name
:
[
message
]
});
done
();
});
});
}
////////////////////////////
...
...
@@ -234,7 +238,7 @@ describe(Helpers.getTestDialectTeaser("DaoValidator"), function() {
for
(
var
j
=
0
;
j
<
validatorDetails
.
pass
.
length
;
j
++
)
{
var
succeedingValue
=
validatorDetails
.
pass
[
j
]
it
(
'correctly specifies an instance as valid using a value of "'
+
succeedingValue
+
'" for the validation "'
+
validator
+
'"'
,
function
()
{
it
(
'correctly specifies an instance as valid using a value of "'
+
succeedingValue
+
'" for the validation "'
+
validator
+
'"'
,
function
(
done
)
{
var
validations
=
{}
if
(
validatorDetails
.
hasOwnProperty
(
'spec'
))
{
...
...
@@ -252,21 +256,30 @@ describe(Helpers.getTestDialectTeaser("DaoValidator"), function() {
}
})
var
successfulUser
=
UserSuccess
.
build
({
name
:
succeedingValue
})
expect
(
successfulUser
.
validate
()).
toBeNull
()
var
successfulUser
=
UserSuccess
.
build
({
name
:
succeedingValue
});
successfulUser
.
validate
().
success
(
function
()
{
expect
(
arguments
.
length
).
toBe
(
0
);
done
();
}).
error
(
function
(
err
)
{
expect
(
err
).
toBe
({})
done
();
});
})
}
}
}
it
(
'correctly validates using custom validation methods'
,
function
()
{
it
(
'correctly validates using custom validation methods'
,
function
(
done
)
{
var
User
=
this
.
sequelize
.
define
(
'User'
+
Math
.
random
(),
{
name
:
{
type
:
Sequelize
.
STRING
,
validate
:
{
customFn
:
function
(
val
)
{
customFn
:
function
(
val
,
next
)
{
if
(
val
!==
"2"
)
{
throw
new
Error
(
"name should equal '2'"
)
next
(
"name should equal '2'"
)
}
else
{
next
()
}
}
}
...
...
@@ -274,16 +287,23 @@ describe(Helpers.getTestDialectTeaser("DaoValidator"), function() {
})
var
failingUser
=
User
.
build
({
name
:
"3"
})
,
errors
=
failingUser
.
validate
()
expect
(
errors
).
not
.
toBeNull
(
null
)
expect
(
errors
).
toEqual
({
name
:
[
"name should equal '2'"
]
})
failingUser
.
validate
().
success
(
function
(
errors
)
{
expect
(
errors
).
toEqual
({
name
:
[
"name should equal '2'"
]
})
var
successfulUser
=
User
.
build
({
name
:
"2"
})
successfulUser
.
validate
().
success
(
function
()
{
expect
(
arguments
.
length
).
toBe
(
0
);
done
();
}).
error
(
function
(
err
)
{
expect
(
err
).
toBe
({});
done
();
})
});
var
successfulUser
=
User
.
build
({
name
:
"2"
})
expect
(
successfulUser
.
validate
()).
toBeNull
()
})
it
(
'skips other validations if allowNull is true and the value is null'
,
function
()
{
it
(
'skips other validations if allowNull is true and the value is null'
,
function
(
done
)
{
var
User
=
this
.
sequelize
.
define
(
'User'
+
Math
.
random
(),
{
age
:
{
type
:
Sequelize
.
INTEGER
,
...
...
@@ -294,20 +314,22 @@ describe(Helpers.getTestDialectTeaser("DaoValidator"), function() {
}
})
var
failingUser
=
User
.
build
({
age
:
-
1
})
,
errors
=
failingUser
.
validate
()
expect
(
errors
).
not
.
toBeNull
(
null
)
expect
(
errors
).
toEqual
({
age
:
[
'must be positive'
]
})
var
successfulUser1
=
User
.
build
({
age
:
null
})
expect
(
successfulUser1
.
validate
()).
toBeNull
()
User
.
build
({
age
:
-
1
})
.
validate
()
.
success
(
function
(
errors
)
{
expect
(
errors
).
not
.
toBeNull
(
null
)
expect
(
errors
).
toEqual
({
age
:
[
'must be positive'
]
})
var
successfulUser2
=
User
.
build
({
age
:
1
})
expect
(
successfulUser2
.
validate
()).
toBeNull
()
User
.
build
({
age
:
null
}).
validate
().
success
(
function
()
{
User
.
build
({
age
:
1
}).
validate
().
success
(
function
()
{
done
()
})
})
})
})
it
(
'validates a model with custom model-wide validation methods'
,
function
()
{
it
(
'validates a model with custom model-wide validation methods'
,
function
(
done
)
{
var
Foo
=
this
.
sequelize
.
define
(
'Foo'
+
Math
.
random
(),
{
field1
:
{
type
:
Sequelize
.
INTEGER
,
...
...
@@ -319,22 +341,31 @@ describe(Helpers.getTestDialectTeaser("DaoValidator"), function() {
}
},
{
validate
:
{
xnor
:
function
()
{
xnor
:
function
(
done
)
{
if
((
this
.
field1
===
null
)
===
(
this
.
field2
===
null
))
{
throw
new
Error
(
'xnor failed'
);
done
(
'xnor failed'
)
}
else
{
done
()
}
}
}
})
var
failingFoo
=
Foo
.
build
({
field1
:
null
,
field2
:
null
})
,
errors
=
failingFoo
.
validate
()
Foo
.
build
({
field1
:
null
,
field2
:
null
})
.
validate
()
.
success
(
function
(
errors
)
{
expect
(
errors
).
not
.
toBeNull
()
expect
(
errors
).
toEqual
({
'xnor'
:
[
'xnor failed'
]
})
expect
(
errors
).
not
.
toBeNull
()
expect
(
errors
).
toEqual
({
'xnor'
:
[
'xnor failed'
]
})
var
successfulFoo
=
Foo
.
build
({
field1
:
33
,
field2
:
null
})
expect
(
successfulFoo
.
validate
()).
toBeNull
()
Foo
.
build
({
field1
:
33
,
field2
:
null
})
.
validate
()
.
success
(
function
(
errors
)
{
expect
(
errors
).
not
.
toBeDefined
()
done
()
})
})
})
})
})
spec/promise.spec.js
View file @
1b5fa1a
...
...
@@ -287,7 +287,7 @@ describe(Helpers.getTestDialectTeaser("Promise"), function () {
expect
(
err
.
validateTest
).
toBeDefined
()
expect
(
err
.
validateTest
).
toBeArray
()
expect
(
err
.
validateTest
[
0
]).
toBeDefined
()
expect
(
err
.
validateTest
[
0
].
indexOf
(
'Invalid integer
:
'
)).
toBeGreaterThan
(
-
1
)
expect
(
err
.
validateTest
[
0
].
indexOf
(
'Invalid integer'
)).
toBeGreaterThan
(
-
1
)
done
()
})
})
...
...
Write
Preview
Markdown
is supported
Attach a file
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to post a comment