client_side_validations 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+ }