Permalink
Browse files

Rewrote OK as a component

  • Loading branch information...
1 parent bde3f2d commit 33bfa8e81562ed4a617d327e251bed8459d99600 @anthonyshort committed Nov 18, 2012
View
@@ -1,3 +1,3 @@
node_modules/*
components/*
-lib/*
+ok.css
View
@@ -1,22 +0,0 @@
-Copyright (c) 2012 Anthony Short
-
-Permission is hereby granted, free of charge, to any person
-obtaining a copy of this software and associated documentation
-files (the "Software"), to deal in the Software without
-restriction, including without limitation the rights to use,
-copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the
-Software is furnished to do so, subject to the following
-conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
-OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-OTHER DEALINGS IN THE SOFTWARE.
View
@@ -1,8 +1,17 @@
{
"name": "ok",
- "version": "0.1.2",
- "main": "./ok.js",
+ "repo": "anthonyshort/ok",
+ "description": "Validate objects against a set of rules",
+ "version": "0.0.1",
+ "keywords": [],
"dependencies": {
- "underscore": ">=1.4"
- }
-}
+ "component/each": "*",
+ "anthonyshort/validates": "*"
+ },
+ "development": {},
+ "license": "MIT",
+ "scripts": [
+ "index.js",
+ "lib/errors.js"
+ ]
+}
View
@@ -2,40 +2,18 @@ module.exports = function(grunt) {
// Project configuration.
grunt.initConfig({
- pkg: '<json:package.json>',
- meta: {
- banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' +
- '<%= grunt.template.today("yyyy-mm-dd") %>\n' +
- '<%= pkg.homepage ? "* " + pkg.homepage + "\n" : "" %>' +
- '* Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>;' +
- ' Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %> */'
- },
- concat: {
- dist: {
- src: [
- '<banner:meta.banner>',
- 'lib/ok.js',
- 'lib/validator.js',
- 'lib/errors.js'
- ],
- dest: 'ok.js'
- }
- },
min: {
dist: {
- src: ['<banner:meta.banner>', '<config:concat.dist.dest>'],
+ src: 'ok.js',
dest: 'ok.min.js'
}
},
- test: {
- files: ['test/**/*.js']
- },
lint: {
- files: ['grunt.js', 'lib/**/*.js', 'test/**/*.js']
+ files: ['grunt.js', 'index.js', 'lib/**/*.js', 'test/**/*.js']
},
watch: {
- files: ['grunt.js', 'src/**/*.coffee', 'test/**/*.coffee'],
- tasks: 'coffee concat test'
+ files: ['grunt.js', 'index.js', 'lib/**/*.js', 'test/**/*.coffee'],
+ tasks: 'test'
},
jshint: {
options: {
@@ -56,16 +34,9 @@ module.exports = function(grunt) {
}
},
coffee: {
- app: {
- src: ['src/*.coffee'],
- dest: 'lib',
- options: {
- bare: false
- }
- },
test: {
- src: ['test/coffee/*.coffee'],
- dest: 'test/specs',
+ src: ['test/src/*.coffee'],
+ dest: 'test/specs/*.js',
options: {
bare: true
}
@@ -74,13 +45,28 @@ module.exports = function(grunt) {
mocha: {
index: ['test/index.html']
},
- uglify: {}
+ shell: {
+ install: {
+ command: "component install -f"
+ },
+ build: {
+ command: "component build -o ./ -s ok -n ok"
+ }
+ },
+ clean: {
+ publish: ['build', 'ok.css']
+ }
});
- // Default task.
- grunt.registerTask('default', 'coffee concat min mocha');
- grunt.registerTask('test', 'coffee mocha');
+ grunt.registerTask('test', 'build coffee mocha');
+ grunt.registerTask('install', 'shell:install');
+ grunt.registerTask('build', 'shell:build clean');
+ grunt.registerTask('publish', 'build min');
+
+ grunt.registerTask('default', 'install build test publish clean');
+
grunt.loadNpmTasks('grunt-coffee');
grunt.loadNpmTasks('grunt-mocha');
-
+ grunt.loadNpmTasks('grunt-contrib');
+ grunt.loadNpmTasks('grunt-shell');
};
View
@@ -0,0 +1,55 @@
+var Errors = require('./lib/errors');
+var validator = require('validates');
+var each = require('each');
+
+module.exports = function(attributes, schema) {
+ errors = new Errors;
+
+ each(schema, function(attribute){
+ var value = attributes[attribute];
+
+ // If the rule is required, this is a special case
+ if(schema[attribute].required === true && value == null) {
+ return errors.add(attribute, 'required');
+ }
+
+ each(schema[attribute], function(type){
+ var ruleValue = schema[attribute][type];
+ var validatorMethod = validator[type];
+ var valid = false;
+
+ // Use a custom validator method
+ if (typeof ruleValue === 'function') {
+ if (ruleValue.call(this, value, attributes) === false) {
+ return errors.add(attribute, type);
+ }
+ }
+
+ // The rule type isn't in the validation object
+ // and a custom validation rule wasn't used
+ if( !validatorMethod ) {
+ return;
+ }
+
+ // If the rule value is a boolean we'll check
+ // that the validation test returns the same boolean
+ // For example, a number rule may be set to false
+ else if(ruleValue === true || ruleValue === false) {
+ valid = validatorMethod(value) === ruleValue;
+ }
+
+ // Otherwise the rule value is being used as options
+ // for the validation method
+ else {
+ valid = validatorMethod(value, ruleValue);
+ }
+
+ if (valid === false) {
+ errors.add(attribute, type);
+ }
+ });
+
+ });
+
+ return errors;
+};
View
@@ -0,0 +1,94 @@
+var each = require('each');
+
+/**
+ * Errors object for storing errors from validation.
+ * This provides a nicer interface for working with
+ * the errors after validating an object
+ */
+function Errors() {
+ this.errors = {};
+ this.length = 0;
+}
+
+/**
+ * Add a new error
+ * @param {String} attr The attribute on which the error occured
+ * @param {String} rule The rule that failed
+ */
+Errors.prototype.add = function(attr, rule) {
+ this.errors[attr] = this.errors[attr] || [];
+
+ // Check if this rule has already been added
+ // as an error. If it has been added then we
+ // won't create a new error
+ var found = false;
+ each(this.errors[attr], function(existingRule){
+ if(existingRule === rule) found = true;
+ });
+
+ if (found === false) {
+ this.length += 1;
+ this.errors[attr].push(rule);
+ }
+
+ return this.errors;
+};
+
+/**
+ * Is an attribute valie
+ * @param {String} attr The attribute you want to check
+ * @return {Boolean}
+ */
+Errors.prototype.isValid = function(attr) {
+ return !(this.errors[attr] != null);
+};
+
+/**
+ * Get the errors for an attribute
+ * @param {String} attr
+ * @return {Boolean}
+ */
+Errors.prototype.get = function(attr) {
+ return this.errors[attr] || false;
+};
+
+/**
+ * Is an attribute invalid?
+ * @param {String} attr
+ * @return {Boolean}
+ */
+Errors.prototype.invalid = function(attr) {
+ if (!this.errors[attr]) {
+ return false;
+ }
+ return this.errors[attr];
+};
+
+/**
+ * Loop through each of the errors for an attribute
+ * @param {String} attr Attribute name
+ * @param {Function} callback Callback function
+ * @return {void}
+ */
+Errors.prototype.each = function(attr, callback) {
+ each(this.errors[attr], callback, this);
+};
+
+/**
+ * Loop over the invalid attributes
+ * @param {Function} callback
+ * @return {void}
+ */
+Errors.prototype.keys = function(callback) {
+ each(this.errors, callback);
+}
+
+/**
+ * Get a JSON format for the errors
+ * @return {Object} JSON version of the errors
+ */
+Errors.prototype.toJSON = function() {
+ return this.errors;
+};
+
+module.exports = Errors;
Oops, something went wrong.

0 comments on commit 33bfa8e

Please sign in to comment.