client_side_validations 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,22 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
22
+ *.gem
data/LICENSE ADDED
@@ -0,0 +1,24 @@
1
+ Copyright (c) 2010, Democratic National Committee
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without
5
+ modification, are permitted provided that the following conditions are met:
6
+ * Redistributions of source code must retain the above copyright
7
+ notice, this list of conditions and the following disclaimer.
8
+ * Redistributions in binary form must reproduce the above copyright
9
+ notice, this list of conditions and the following disclaimer in the
10
+ documentation and/or other materials provided with the distribution.
11
+ * Neither the name of the Democratic National Committee nor the
12
+ names of its contributors may be used to endorse or promote products
13
+ derived from this software without specific prior written permission.
14
+
15
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
+ DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
19
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/README.rdoc ADDED
@@ -0,0 +1,17 @@
1
+ = ar_client_side_validations
2
+
3
+ ActiveRecord Client Side Validations
4
+
5
+ == Note on Patches/Pull Requests
6
+
7
+ * Fork the project.
8
+ * Make your feature addition or bug fix.
9
+ * Add tests for it. This is important so I don't break it in a
10
+ future version unintentionally.
11
+ * Commit, do not mess with rakefile, version, or history.
12
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
13
+ * Send me a pull request. Bonus points for topic branches.
14
+
15
+ == Copyright
16
+
17
+ Copyright (c) 2010 Democratic National Committee. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,47 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "client_side_validations"
8
+ gem.summary = %Q{Client Side Validations}
9
+ gem.description = %Q{ORM and Framework agnostic Client Side Validations}
10
+ gem.email = "cardarellab@dnc.org"
11
+ gem.homepage = "http://github.com/dnclabs/client_side_validations"
12
+ gem.authors = ["Brian Cardarella"]
13
+ gem.add_development_dependency "rspec", ">= 1.2.9"
14
+ gem.add_dependency 'validation_reflection', '>= 0.3.6'
15
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
16
+ end
17
+ Jeweler::GemcutterTasks.new
18
+ rescue LoadError
19
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
20
+ end
21
+
22
+ require 'spec/rake/spectask'
23
+ Spec::Rake::SpecTask.new(:spec) do |spec|
24
+ spec.libs << 'lib' << 'spec'
25
+ spec.spec_files = FileList['spec/**/*_spec.rb']
26
+ end
27
+
28
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
29
+ spec.libs << 'lib' << 'spec'
30
+ spec.pattern = 'spec/**/*_spec.rb'
31
+ spec.rcov = true
32
+ end
33
+
34
+ task :spec => :check_dependencies
35
+ task :default => :spec
36
+
37
+ require 'rake/rdoctask'
38
+ Rake::RDocTask.new do |rdoc|
39
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
40
+
41
+ rdoc.rdoc_dir = 'rdoc'
42
+ rdoc.title = "ar_client_side_validations #{version}"
43
+ rdoc.rdoc_files.include('README*')
44
+ rdoc.rdoc_files.include('lib/**/*.rb')
45
+ end
46
+
47
+ Dir['tasks/**/*.rake'].each { |t| load t }
data/TODO ADDED
@@ -0,0 +1,2 @@
1
+ - Add Rails Generators
2
+ - Check ActionView code against Rails 3
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.6.0
@@ -0,0 +1,79 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{client_side_validations}
8
+ s.version = "0.6.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Brian Cardarella"]
12
+ s.date = %q{2010-06-07}
13
+ s.description = %q{ORM and Framework agnostic Client Side Validations}
14
+ s.email = %q{cardarellab@dnc.org}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.rdoc",
18
+ "TODO"
19
+ ]
20
+ s.files = [
21
+ ".document",
22
+ ".gitignore",
23
+ "LICENSE",
24
+ "README.rdoc",
25
+ "Rakefile",
26
+ "TODO",
27
+ "VERSION",
28
+ "client_side_validations.gemspec",
29
+ "javascript/jspec/commands/example_command.rb",
30
+ "javascript/jspec/rhino.js",
31
+ "javascript/jspec/unit/jquery.validate.spec.js",
32
+ "javascript/jspec/unit/spec.helper.js",
33
+ "javascript/lib/client_side_validations.js",
34
+ "javascript/vendor/jspec.js",
35
+ "javascript/vendor/jspec.xhr.js",
36
+ "lib/adapters/action_view.rb",
37
+ "lib/adapters/active_model.rb",
38
+ "lib/adapters/active_record_2.rb",
39
+ "lib/client_side_validations.rb",
40
+ "spec/action_view_2_spec.rb",
41
+ "spec/action_view_3_spec.rb",
42
+ "spec/active_model_3_spec.rb",
43
+ "spec/active_record_2_spec.rb",
44
+ "spec/spec.opts",
45
+ "spec/spec_helper.rb",
46
+ "spec/support/required_gems.rb",
47
+ "tasks/spec.rake"
48
+ ]
49
+ s.homepage = %q{http://github.com/dnclabs/client_side_validations}
50
+ s.rdoc_options = ["--charset=UTF-8"]
51
+ s.require_paths = ["lib"]
52
+ s.rubygems_version = %q{1.3.6}
53
+ s.summary = %q{Client Side Validations}
54
+ s.test_files = [
55
+ "spec/action_view_2_spec.rb",
56
+ "spec/action_view_3_spec.rb",
57
+ "spec/active_model_3_spec.rb",
58
+ "spec/active_record_2_spec.rb",
59
+ "spec/spec_helper.rb",
60
+ "spec/support/required_gems.rb"
61
+ ]
62
+
63
+ if s.respond_to? :specification_version then
64
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
65
+ s.specification_version = 3
66
+
67
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
68
+ s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
69
+ s.add_runtime_dependency(%q<validation_reflection>, [">= 0.3.6"])
70
+ else
71
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
72
+ s.add_dependency(%q<validation_reflection>, [">= 0.3.6"])
73
+ end
74
+ else
75
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
76
+ s.add_dependency(%q<validation_reflection>, [">= 0.3.6"])
77
+ end
78
+ end
79
+
@@ -0,0 +1,19 @@
1
+
2
+ # uncomment and call with `$ jspec example `
3
+
4
+ # command :example do |c|
5
+ # c.syntax = 'jspec example [options]'
6
+ # c.description = 'Just an example command'
7
+ # c.option '-f', '--foo string', 'Does some foo with <string>'
8
+ # c.option '-b', '--bar [string]', 'Does some bar with [string]'
9
+ # c.example 'Do some foo', 'jspec example --foo bar'
10
+ # c.example 'Do some bar', 'jspec example --bar'
11
+ # c.when_called do |args, options|
12
+ # p args
13
+ # p options.__hash__
14
+ # # options.foo
15
+ # # options.bar
16
+ # # options.__hash__[:foo]
17
+ # # options.__hash__[:bar]
18
+ # end
19
+ # end
@@ -0,0 +1,10 @@
1
+
2
+ load('vendor/jspec.js')
3
+ load('vendor/jspec.xhr.js')
4
+ load('lib/client_side_validations.js')
5
+ load('jspec/unit/spec.helper.js')
6
+
7
+ JSpec
8
+ .exec('jspec/unit/jquery.validate.spec.js')
9
+ .run({ reporter: JSpec.reporters.Terminal, fixturePath: 'spec/fixtures' })
10
+ .report()
@@ -0,0 +1,146 @@
1
+ describe 'jquery.validate adapter'
2
+ before
3
+ client = new ClientSideValidations('object', 'jquery.validate');
4
+ end
5
+
6
+ describe 'required'
7
+ before
8
+ validations = {
9
+ "number": {
10
+ "presence": { "message":"can't be blank" }
11
+ }
12
+ }
13
+ result = client.adaptValidations(validations);
14
+ end
15
+
16
+ it 'should translate the rule'
17
+ result.rules['object[number]']['required'].should.be_true
18
+ end
19
+
20
+ it 'should translate the message'
21
+ result.messages['object[number]']['required'].should.equal "can't be blank"
22
+ end
23
+ end
24
+
25
+ describe 'format'
26
+ before
27
+ validations = {
28
+ "number": {
29
+ "format": { "message":"is invalid", "with":/\d/ }
30
+ }
31
+ }
32
+ result = client.adaptValidations(validations)
33
+ end
34
+
35
+ it 'should translate the rule'
36
+ result.rules['object[number]']['format'].should.eql(/\d/)
37
+ end
38
+
39
+ it 'should translate the message'
40
+ result.messages['object[number]']['format'].should.equal "is invalid"
41
+ end
42
+ end
43
+
44
+ describe 'digits'
45
+ before
46
+ validations = {
47
+ "number": {
48
+ "numericality": { "message":"is not a number" }
49
+ }
50
+ }
51
+ result = client.adaptValidations(validations)
52
+ end
53
+
54
+ it 'should translate the rule'
55
+ result.rules['object[number]']['digits'].should.be_true
56
+ end
57
+
58
+ it 'should translate the message'
59
+ result.messages['object[number]']['digits'].should.equal "is not a number"
60
+ end
61
+ end
62
+
63
+ describe 'minlength'
64
+ before
65
+ validations = {
66
+ "string": {
67
+ "length": { "message":"is too short (minimum is 10 characters)", "minimum":10 }
68
+ }
69
+ }
70
+ result = client.adaptValidations(validations)
71
+ end
72
+
73
+ it 'should translate the rule'
74
+ result.rules['object[string]']['minlength'].should.eql(10)
75
+ end
76
+
77
+ it 'should translate the message'
78
+ result.messages['object[string]']['minlength'].should.equal "is too short (minimum is 10 characters)"
79
+ end
80
+ end
81
+
82
+ describe 'maxlength'
83
+ before
84
+ validations = {
85
+ "string": {
86
+ "length": { "message":"is too short (maximum is 10 characters)", "maximum":10 }
87
+ }
88
+ }
89
+ result = client.adaptValidations(validations)
90
+ end
91
+
92
+ it 'should translate the rule'
93
+ result.rules['object[string]']['maxlength'].should.eql(10)
94
+ end
95
+
96
+ it 'should translate the message'
97
+ result.messages['object[string]']['maxlength'].should.equal "is too short (maximum is 10 characters)"
98
+ end
99
+ end
100
+
101
+ describe 'multiple attributes'
102
+ before
103
+ validations = {
104
+ "number_1": {
105
+ "presence": { "message":"can't be blank" }
106
+ },
107
+ "number_2": {
108
+ "presence": { "message":"can't be blank" }
109
+ }
110
+ }
111
+ result = client.adaptValidations(validations)
112
+ end
113
+
114
+ it 'should translate the rules for both attributes'
115
+ result.rules['object[number_1]']['required'].should.be_true
116
+ result.rules['object[number_2]']['required'].should.be_true
117
+ end
118
+
119
+ it 'should translate the messages for both attributes'
120
+ result.messages['object[number_1]']['required'].should.eql("can't be blank")
121
+ result.messages['object[number_2]']['required'].should.eql("can't be blank")
122
+ end
123
+ end
124
+
125
+ describe 'multiple rules'
126
+ before
127
+ validations = {
128
+ "number": {
129
+ "presence": { "message":"can't be blank" },
130
+ "numericality": { "message":"is not a number" }
131
+ }
132
+ }
133
+ result = client.adaptValidations(validations)
134
+ end
135
+
136
+ it 'should translate the rules for both attributes'
137
+ result.rules['object[number]']['required'].should.be_true
138
+ result.rules['object[number]']['digits'].should.be_true
139
+ end
140
+
141
+ it 'should translate the messages for both attributes'
142
+ result.messages['object[number]']['required'].should.eql("can't be blank")
143
+ result.messages['object[number]']['digits'].should.eql("is not a number")
144
+ end
145
+ end
146
+ end
File without changes
@@ -0,0 +1,92 @@
1
+ /* Additional jQueryValidator methods */
2
+
3
+ if (typeof(jQuery) != "undefined") {
4
+ if (typeof($('').validate) != "undefined") {
5
+ jQuery.validator.addMethod("format", function(value, element, params) {
6
+ var pattern = new RegExp(params, "i");
7
+ return this.optional(element) || pattern.test(value);
8
+ }, jQuery.validator.format("Invalid format."));
9
+ }
10
+ }
11
+
12
+ $.extend($.fn, {
13
+ clientSideValidations: function(url, adapter) {
14
+ var form = this;
15
+ var id = form[0].id;
16
+ if (/new/.test(id)) {
17
+ id = /new_(\w+)/.exec(id)[1]
18
+ } else if (/edit/.test(id)) {
19
+ id = /edit_(\w+)_\d+/.exec(id)[1]
20
+ }
21
+ var client = new ClientSideValidations(id, adapter)
22
+ $.getJSON(url, function(json) {
23
+ var validations = client.adaptValidations(json);
24
+ form.validate({
25
+ rules: validations.rules,
26
+ messages: validations.messages
27
+ });
28
+ });
29
+ }
30
+ });
31
+
32
+ ClientSideValidations = function(id, adapter) {
33
+ this.id = id;
34
+ this.adapter = adapter;
35
+ this.adaptValidations = function(validations) {
36
+ this.validations = validations;
37
+ this.jQueryValidateAdapter = function() {
38
+ rules = {}
39
+ messages = {}
40
+ for(var attr in this.validations) {
41
+ name = this.id + '[' + attr + ']';
42
+ rules[name] = {};
43
+ messages[name] = {};
44
+ for(var validation in this.validations[attr]) {
45
+ rule = null;
46
+ switch(validation) {
47
+ case 'presence':
48
+ rule = 'required'
49
+ value = true;
50
+ break;
51
+ case 'format':
52
+ value = this.validations[attr][validation]['with'];
53
+ break;
54
+ case 'numericality':
55
+ rule = 'digits';
56
+ value = true;
57
+ break;
58
+ case 'length':
59
+ if('minimum' in this.validations[attr][validation]) {
60
+ rule = 'minlength';
61
+ value = this.validations[attr][validation]['minimum'];
62
+ } else if('maximum' in this.validations[attr][validation]) {
63
+ rule = 'maxlength';
64
+ value = this.validations[attr][validation]['maximum'];
65
+ }
66
+ break;
67
+ default:
68
+ }
69
+ if(rule == null) {
70
+ rule = validation;
71
+ }
72
+ rules[name][rule] = value;
73
+ messages[name][rule] = this.validations[attr][validation]['message'];
74
+ }
75
+ }
76
+
77
+ result = {
78
+ rules : rules,
79
+ messages : messages
80
+ };
81
+
82
+ return result;
83
+ };
84
+
85
+ switch(this.adapter) {
86
+ case 'jquery.validate':
87
+ return this.jQueryValidateAdapter();
88
+ break;
89
+ default:
90
+ }
91
+ };
92
+ }