client_side_validations 2.2.2 → 2.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +5 -3
- data/javascript/lib/client_side_validations.js +22 -19
- data/lib/client_side_validations.rb +40 -46
- data/lib/client_side_validations/adapters/action_view.rb +78 -14
- data/lib/client_side_validations/adapters/active_model.rb +2 -0
- data/lib/client_side_validations/adapters/active_record_2.rb +4 -0
- metadata +4 -4
data/README.markdown
CHANGED
@@ -17,6 +17,7 @@ Currently the following validations are supported:
|
|
17
17
|
* validates_numericality_of
|
18
18
|
* validates_length_of
|
19
19
|
* validates_uniqueness_of
|
20
|
+
* validates_confirmation_of
|
20
21
|
|
21
22
|
The uniqueness validation works for both ActiveRecord and Mongoid.
|
22
23
|
|
@@ -43,9 +44,10 @@ This will copy client_side_validations.js to "public/javascripts"
|
|
43
44
|
Currently only [jquery.validate](http://bassistance.de/jquery-plugins/jquery-plugin-validation/) is supported so you will need to download [jQuery](http://docs.jquery.com/Downloading_jQuery) and the jQuery Validate plugin to "public/javascripts"
|
44
45
|
|
45
46
|
### Rack
|
46
|
-
|
47
|
+
If you want to validate_uniqueness_of a call to the server must be made. You can do this by simply drop in the ClidenSideValidations Rack middleware.
|
48
|
+
|
49
|
+
The following route will be reserved for client side validations:
|
47
50
|
|
48
|
-
/validations.json
|
49
51
|
/validations/uniqueness.json
|
50
52
|
|
51
53
|
Add the middleware to your stack:
|
@@ -55,7 +57,7 @@ config/environment.rb for Rails 2.x
|
|
55
57
|
config/application.rb for Rails 3.x
|
56
58
|
|
57
59
|
...
|
58
|
-
config.middleware.use 'ClientSideValidations'
|
60
|
+
config.middleware.use 'ClientSideValidations::Uniqueness'
|
59
61
|
...
|
60
62
|
|
61
63
|
### Model
|
@@ -6,29 +6,28 @@ if (typeof(jQuery) != "undefined") {
|
|
6
6
|
|
7
7
|
$.extend($.fn, {
|
8
8
|
clientSideValidations: function() {
|
9
|
-
var form
|
10
|
-
var object
|
11
|
-
var
|
12
|
-
var
|
13
|
-
var
|
14
|
-
var object_id = null;
|
15
|
-
if (edit_pattern.test(id)) {
|
16
|
-
object_id = Number(edit_pattern.exec(id)[1]);
|
17
|
-
}
|
18
|
-
var adapter = 'jquery.validate';
|
9
|
+
var form = this;
|
10
|
+
var object = form.attr('object-csv');
|
11
|
+
var id = form[0].id;
|
12
|
+
var object_id = null;
|
13
|
+
var adapter = 'jquery.validate';
|
19
14
|
if (/new/.test(id)) {
|
20
15
|
id = /new_(\w+)/.exec(id)[1]
|
21
16
|
} else if (/edit/.test(id)) {
|
22
|
-
id
|
17
|
+
id = /edit_(\w+)_\d+/.exec(id)[1]
|
18
|
+
object_id = /edit_\w+_(\d+)/.exec(id)[1]
|
19
|
+
}
|
20
|
+
if (eval("typeof(" + object + "_validation_options)") != "undefined") {
|
21
|
+
var options = eval(object + '_validation_options');
|
22
|
+
} else {
|
23
|
+
var options = { }
|
23
24
|
}
|
24
|
-
var client
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
});
|
31
|
-
});
|
25
|
+
var client = new ClientSideValidations(id, adapter, object_id)
|
26
|
+
var rules = eval(object + '_validation_rules');
|
27
|
+
var validations = client.adaptValidations(rules);
|
28
|
+
options['rules'] = validations.rules;
|
29
|
+
options['messages'] = validations.messages;
|
30
|
+
form.validate(options);
|
32
31
|
}
|
33
32
|
});
|
34
33
|
|
@@ -84,6 +83,10 @@ ClientSideValidations = function(id, adapter, object_id) {
|
|
84
83
|
}
|
85
84
|
}
|
86
85
|
break;
|
86
|
+
case 'confirmation':
|
87
|
+
rule = 'equalTo';
|
88
|
+
value = "[name='" + this.id + "[" + attr + "_confirmation]" + "']";
|
89
|
+
break;
|
87
90
|
|
88
91
|
default:
|
89
92
|
}
|
@@ -2,63 +2,57 @@ require 'rubygems'
|
|
2
2
|
require 'json'
|
3
3
|
require 'cgi'
|
4
4
|
|
5
|
-
|
6
|
-
def
|
7
|
-
@
|
5
|
+
module ClientSideValidations
|
6
|
+
def self.default_options=(options)
|
7
|
+
@default_options = options
|
8
8
|
end
|
9
9
|
|
10
|
-
def
|
11
|
-
|
12
|
-
# We need to override this
|
13
|
-
params = {}.merge!(CGI::parse(env['QUERY_STRING']))
|
14
|
-
case env['PATH_INFO']
|
15
|
-
when %r{^/validations.json}
|
16
|
-
body = get_validations(params['model'][0])
|
17
|
-
[200, {'Content-Type' => 'application/json', 'Content-Length' => "#{body.length}"}, body]
|
18
|
-
when %r{^/validations/uniqueness.json}
|
19
|
-
field = params.keys.first
|
20
|
-
resource, attribute = field.split(/[^\w]/)
|
21
|
-
value = params[field][0]
|
22
|
-
# Because params returns an array for each field value we want to always grab
|
23
|
-
# the first element of the array for id, even if it is nil
|
24
|
-
id = [params["#{resource}[id]"]].flatten.first
|
25
|
-
body = is_unique?(resource, attribute, value, id).to_s
|
26
|
-
[200, {'Content-Type' => 'application/json', 'Content-Length' => "#{body.length}"}, body]
|
27
|
-
else
|
28
|
-
@app.call(env)
|
29
|
-
end
|
10
|
+
def self.default_options
|
11
|
+
@default_options
|
30
12
|
end
|
31
13
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
end
|
14
|
+
class Uniqueness
|
15
|
+
def initialize(app)
|
16
|
+
@app = app
|
17
|
+
end
|
37
18
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
19
|
+
def call(env)
|
20
|
+
# By default CGI::parse will instantize a hash that defaults nil elements to [].
|
21
|
+
# We need to override this
|
22
|
+
case env['PATH_INFO']
|
23
|
+
when %r{^/validations/uniqueness.json}
|
24
|
+
params = {}.merge!(CGI::parse(env['QUERY_STRING']))
|
25
|
+
field = params.keys.first
|
26
|
+
resource, attribute = field.split(/[^\w]/)
|
27
|
+
value = params[field][0]
|
28
|
+
# Because params returns an array for each field value we want to always grab
|
29
|
+
# the first element of the array for id, even if it is nil
|
30
|
+
id = [params["#{resource}[id]"]].flatten.first
|
31
|
+
body = is_unique?(resource, attribute, value, id).to_s
|
32
|
+
[200, {'Content-Type' => 'application/json', 'Content-Length' => "#{body.length}"}, body]
|
33
|
+
else
|
34
|
+
@app.call(env)
|
48
35
|
end
|
49
36
|
end
|
50
|
-
|
51
|
-
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def is_unique?(resource, attribute, value, id = nil)
|
41
|
+
klass = constantize_resource(resource)
|
42
|
+
instance = nil
|
52
43
|
instance = klass.send("find_by_#{attribute}", value)
|
53
|
-
end
|
54
44
|
|
55
|
-
|
56
|
-
|
45
|
+
if instance
|
46
|
+
return instance.id.to_i == id.to_i
|
47
|
+
else
|
48
|
+
return true
|
49
|
+
end
|
50
|
+
end
|
57
51
|
|
58
|
-
|
59
|
-
|
52
|
+
def constantize_resource(resource)
|
53
|
+
eval(resource.split('_').map{ |word| word.capitalize}.join)
|
54
|
+
end
|
60
55
|
end
|
61
|
-
|
62
56
|
end
|
63
57
|
|
64
58
|
require 'client_side_validations/orm'
|
@@ -10,34 +10,98 @@ module DNCLabs
|
|
10
10
|
define_method(:form_for) do |record_or_name_or_array, *args, &proc|
|
11
11
|
options = args.extract_options!
|
12
12
|
options.symbolize_keys!
|
13
|
+
script = ""
|
13
14
|
if validations = options.delete(:validations)
|
14
15
|
unless options.key?(:html)
|
15
16
|
options[:html] = {}
|
16
17
|
end
|
17
|
-
|
18
|
-
unless validations == true
|
19
|
-
object = validations.to_s.underscore
|
20
|
-
else
|
21
|
-
case record_or_name_or_array
|
22
|
-
when String, Symbol
|
23
|
-
object = record_or_name_or_array.to_s
|
24
|
-
else
|
25
|
-
object = record_or_name_or_array.class.to_s.underscore
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
18
|
+
object, rules, csv_options = csv_get_variables(validations, record_or_name_or_array)
|
29
19
|
options[:html]['object-csv'] = object
|
20
|
+
csv_rules = %{var #{object}_validation_rules=#{rules};}
|
21
|
+
script = %{<script type='text/javascript'>#{csv_rules}#{csv_options}</script>}
|
30
22
|
end
|
31
23
|
args << options
|
32
|
-
form_method.bind(self).call(record_or_name_or_array, *args, &proc)
|
24
|
+
result = form_method.bind(self).call(record_or_name_or_array, *args, &proc)
|
25
|
+
|
26
|
+
if rails3?
|
27
|
+
result += script.html_safe
|
28
|
+
else
|
29
|
+
concat(script)
|
30
|
+
end
|
31
|
+
result
|
33
32
|
end
|
34
33
|
end
|
35
34
|
end
|
36
35
|
|
36
|
+
private
|
37
|
+
|
38
|
+
def rails3?
|
39
|
+
version=
|
40
|
+
if defined?(ActionPack::VERSION::MAJOR)
|
41
|
+
ActionPack::VERSION::MAJOR
|
42
|
+
end
|
43
|
+
!version.blank? && version >= 3
|
44
|
+
end
|
45
|
+
|
46
|
+
def csv_get_variables(validations, record_or_name_or_array)
|
47
|
+
csv_options = ::ClientSideValidations.default_options || { }
|
48
|
+
case validations
|
49
|
+
when true
|
50
|
+
object, rules = csv_get_object_and_validation_rules(record_or_name_or_array)
|
51
|
+
when Hash
|
52
|
+
validations.symbolize_keys!
|
53
|
+
if validations.has_key?(:instance)
|
54
|
+
object = validations[:instance].class.to_s.underscore
|
55
|
+
rules = validations[:instance].validations_to_json
|
56
|
+
elsif validations.has_key?(:class)
|
57
|
+
object = validations[:instance].to_s.underscore
|
58
|
+
rules = validations[:instance].new.validations_to_json
|
59
|
+
else
|
60
|
+
object, rules = csv_get_object_and_validation_rules(record_or_name_or_array)
|
61
|
+
end
|
62
|
+
if validations.has_key?(:options)
|
63
|
+
csv_options.merge!(validations[:options])
|
64
|
+
end
|
65
|
+
else
|
66
|
+
object = validations.to_s.underscore
|
67
|
+
rules = validations.new.validations_to_json
|
68
|
+
end
|
69
|
+
|
70
|
+
if csv_options.empty?
|
71
|
+
csv_options = ""
|
72
|
+
else
|
73
|
+
csv_options = %{var #{object}_validation_options=#{convert_csv_options_to_json(csv_options)};}
|
74
|
+
end
|
75
|
+
|
76
|
+
[object, rules, csv_options]
|
77
|
+
end
|
78
|
+
|
79
|
+
def convert_csv_options_to_json(csv_options)
|
80
|
+
json = []
|
81
|
+
csv_options.each do |k, v|
|
82
|
+
json << %{#{k}:#{v}}
|
83
|
+
end
|
84
|
+
%{{#{json.join(',')}}}
|
85
|
+
end
|
86
|
+
|
87
|
+
def csv_get_object_and_validation_rules(record_or_name_or_array)
|
88
|
+
case record_or_name_or_array
|
89
|
+
when String, Symbol
|
90
|
+
object = record_or_name_or_array.to_s
|
91
|
+
rules = object.camelize.constantize.new.validations_to_json
|
92
|
+
when Array
|
93
|
+
object, rules = csv_get_object_and_validation_rules(record_or_name_or_array.last)
|
94
|
+
else
|
95
|
+
object = record_or_name_or_array.class.to_s.underscore
|
96
|
+
rules = record_or_name_or_array.validations_to_json
|
97
|
+
end
|
98
|
+
|
99
|
+
[object, rules]
|
100
|
+
end
|
37
101
|
end # BaseMethods
|
38
102
|
|
39
103
|
module FormBuilderMethods
|
40
|
-
|
104
|
+
|
41
105
|
def client_side_validations(options = {})
|
42
106
|
@template.send(:client_side_validations, @object_name, objectify_options(options))
|
43
107
|
end
|
@@ -61,6 +61,8 @@ module DNCLabs
|
|
61
61
|
elsif defined?(Mongoid) && base.class.included_modules.include?(Mongoid::Document)
|
62
62
|
I18n.translate('errors.messages.taken', :locale => locale)
|
63
63
|
end
|
64
|
+
when :confirmation
|
65
|
+
I18n.translate('errors.messages.confirmation', :locale => locale)
|
64
66
|
end
|
65
67
|
|
66
68
|
message = validation.options[:message]
|
@@ -57,6 +57,8 @@ module DNCLabs
|
|
57
57
|
I18n.translate('activerecord.errors.messages.not_a_number', :locale => locale)
|
58
58
|
when 'validates_uniqueness_of'
|
59
59
|
I18n.translate('activerecord.errors.messages.taken', :locale => locale)
|
60
|
+
when 'validates_confirmation_of'
|
61
|
+
I18n.translate('activerecord.errors.messages.confirmation', :locale => locale)
|
60
62
|
end
|
61
63
|
|
62
64
|
message = validation.options[:message]
|
@@ -90,6 +92,8 @@ module DNCLabs
|
|
90
92
|
'length'
|
91
93
|
when 'validates_uniqueness_of'
|
92
94
|
'uniqueness'
|
95
|
+
when 'validates_confirmation_of'
|
96
|
+
'confirmation'
|
93
97
|
end
|
94
98
|
end
|
95
99
|
end
|
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 2
|
7
|
-
-
|
8
|
-
-
|
9
|
-
version: 2.
|
7
|
+
- 3
|
8
|
+
- 0
|
9
|
+
version: 2.3.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Brian Cardarella
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-07-
|
17
|
+
date: 2010-07-09 00:00:00 -04:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|