Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/Validators.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ validators.unique = function () {
var chainQuery = function (prop, value) {
var query = null;

if (opts.ignoreCase === true && ctx.model.properties[prop].type === 'text') {
if (opts.ignoreCase === true && ctx.model.properties[prop] && ctx.model.properties[prop].type === 'text') {
query = util.format('LOWER(%s.%s) LIKE LOWER(?)',
ctx.driver.query.escapeId(ctx.model.table), ctx.driver.query.escapeId(prop)
);
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"sqlite",
"mongodb"
],
"version" : "2.1.21",
"version" : "2.1.22",
"license" : "MIT",
"homepage" : "http://dresende.github.io/node-orm2",
"repository" : "http://github.com/dresende/node-orm2.git",
Expand Down
104 changes: 89 additions & 15 deletions test/integration/validation.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,23 +111,36 @@ describe("Validations", function() {
describe("unique", function () {
if (protocol === "mongodb") return;

var Product = null;
var Product = null, Supplier = null;

var setupUnique = function (ignoreCase, scope, msg) {
return function (done) {
Product = db.define("productUnique", {
instock : { type: 'boolean', required: true, defaultValue: false },
name : String,
category : String
}, {
cache: false,
validations: {
name : ORM.validators.unique({ ignoreCase: ignoreCase, scope: scope }, msg),
instock : ORM.validators.required(),
productId : ORM.validators.unique() // this must be straight after a required & validated row.
Supplier = db.define("supplier", {
name : String
}, {
cache: false
});
helper.dropSync(Supplier, function(err){
if (err) {
return done(err);
}

Product = db.define("productUnique", {
instock : { type: 'boolean', required: true, defaultValue: false },
name : String,
category : String
}, {
cache: false,
validations: {
name : ORM.validators.unique({ ignoreCase: ignoreCase, scope: scope }, msg),
instock : ORM.validators.required(),
productId : ORM.validators.unique() // this must be straight after a required & validated row.
}
});
Product.hasOne('supplier', Supplier, { field: 'supplierId' });

return helper.dropSync(Product, done);
});
return helper.dropSync(Product, done);
};
};

Expand Down Expand Up @@ -174,7 +187,8 @@ describe("Validations", function() {

describe("scope", function () {
describe("to other property", function () {
before(setupUnique(false, ['category']));

before(setupUnique(true, ['category']));

it("should return validation error if other property also matches", function(done) {
Product.create({name: 'red', category: 'chair'}, function (err, product) {
Expand All @@ -189,7 +203,7 @@ describe("Validations", function() {
});
});

it("should pass if other peroperty is different", function (done) {
it("should pass if other property is different", function (done) {
Product.create({name: 'blue', category: 'chair'}, function (err, product) {
should.not.exist(err);

Expand All @@ -202,7 +216,67 @@ describe("Validations", function() {
});

// In SQL unique index land, NULL values are not considered equal.
it("should pass if other peroperty is null", function (done) {
it("should pass if other property is null", function (done) {
Product.create({name: 'blue', category: null}, function (err, product) {
should.not.exist(err);

Product.create({name: 'blue', category: null}, function (err, product) {
should.not.exist(err);

return done();
});
});
});
});

describe("to hasOne property", function () {
firstId = secondId = null;

before(function(done){
setupUnique(true, ['supplierId'])(function(err) {
should.not.exist(err);
Supplier.create({name: 'first'}, function (err, supplier) {
should.not.exist(err);

firstId = supplier.id;

Supplier.create({name: 'second'}, function (err, supplier) {
should.not.exist(err);

secondId = supplier.id;
done();
});
});
});
});

it("should return validation error if hasOne property also matches", function(done) {
Product.create({name: 'red', supplierId: firstId}, function (err, product) {
should.not.exist(err);

Product.create({name: 'red', supplierId: firstId}, function (err, product) {
should.exist(err);
should.equal(err.msg, 'not-unique');

return done();
});
});
});

it("should pass if hasOne property is different", function (done) {
Product.create({name: 'blue', supplierId: firstId}, function (err, product) {
should.not.exist(err);

Product.create({name: 'blue', supplierId: secondId}, function (err, product) {
should.not.exist(err);

return done();
});
});
});

// In SQL unique index land, NULL values are not considered equal.
it("should pass if other property is null", function (done) {
Product.create({name: 'blue', category: null}, function (err, product) {
should.not.exist(err);

Expand Down