client_side_validations 3.0.4 → 3.0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/client_side_validations.gemspec +2 -3
- data/javascript/rails.validations.js +26 -12
- data/lib/client_side_validations.rb +2 -0
- data/lib/client_side_validations/action_view/form_builder.rb +55 -5
- data/lib/client_side_validations/action_view/form_helper.rb +20 -2
- data/lib/client_side_validations/active_model.rb +22 -13
- data/lib/client_side_validations/active_model/length.rb +12 -10
- data/lib/client_side_validations/active_model/numericality.rb +14 -9
- data/lib/client_side_validations/active_record/middleware.rb +5 -1
- data/lib/client_side_validations/active_record/uniqueness.rb +10 -8
- data/lib/client_side_validations/middleware.rb +2 -0
- data/lib/client_side_validations/mongo_mapper.rb +9 -0
- data/lib/client_side_validations/mongo_mapper/middleware.rb +20 -0
- data/lib/client_side_validations/mongo_mapper/uniqueness.rb +28 -0
- data/lib/client_side_validations/mongoid/uniqueness.rb +10 -8
- data/lib/client_side_validations/version.rb +1 -1
- data/test/action_view/cases/helper.rb +7 -1
- data/test/action_view/cases/test_helpers.rb +263 -0
- data/test/action_view/cases/test_legacy_helpers.rb +11 -0
- data/test/active_model/cases/test_validations.rb +21 -8
- data/test/active_record/cases/test_middleware.rb +25 -0
- data/test/active_record/cases/test_uniqueness_validator.rb +5 -0
- data/test/active_record/models/user.rb +4 -0
- data/test/formtastic/cases/test_form_helper.rb +1 -1
- data/test/javascript/public/test/callbacks/elementAfter.js +1 -1
- data/test/javascript/public/test/callbacks/elementBefore.js +1 -1
- data/test/javascript/public/test/callbacks/elementFail.js +1 -1
- data/test/javascript/public/test/callbacks/elementPass.js +1 -1
- data/test/javascript/public/test/callbacks/formAfter.js +1 -1
- data/test/javascript/public/test/callbacks/formBefore.js +1 -1
- data/test/javascript/public/test/callbacks/formFail.js +1 -1
- data/test/javascript/public/test/callbacks/formPass.js +1 -1
- data/test/javascript/public/test/form_builders/validateForm.js +1 -1
- data/test/javascript/public/test/form_builders/validateFormtastic.js +1 -1
- data/test/javascript/public/test/form_builders/validateNestedForm.js +66 -0
- data/test/javascript/public/test/form_builders/validateSimpleForm.js +1 -1
- data/test/javascript/public/test/validateElement.js +36 -1
- data/test/javascript/public/test/validators/length.js +7 -1
- data/test/javascript/public/test/validators/numericality.js +7 -0
- data/test/javascript/public/test/validators/presence.js +6 -0
- data/test/javascript/public/test/validators/uniqueness.js +8 -1
- data/test/javascript/server.rb +7 -1
- data/test/javascript/views/index.erb +1 -1
- data/test/mongo_mapper/cases/helper.rb +9 -0
- data/test/mongo_mapper/cases/test_base.rb +15 -0
- data/test/mongo_mapper/cases/test_middleware.rb +77 -0
- data/test/mongo_mapper/cases/test_uniqueness_validator.rb +50 -0
- data/test/mongo_mapper/models/magazine.rb +11 -0
- data/test/mongoid/cases/test_middleware.rb +9 -0
- data/test/mongoid/cases/test_uniqueness_validator.rb +5 -0
- data/test/mongoid/models/book.rb +4 -0
- data/test/simple_form/cases/test_form_helper.rb +1 -1
- metadata +46 -20
@@ -12,19 +12,18 @@ Gem::Specification.new do |s|
|
|
12
12
|
s.summary = %q{Client Side Validations}
|
13
13
|
s.description = %q{Client Side Validations}
|
14
14
|
|
15
|
-
s.rubyforge_project = "client_side_validations"
|
16
|
-
|
17
15
|
s.files = `git ls-files -- {lib/*,javascript/*,*.gemspec}`.split("\n")
|
18
16
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
17
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
18
|
s.require_paths = ["lib"]
|
21
19
|
|
22
|
-
s.add_dependency 'activesupport'
|
20
|
+
s.add_dependency 'activesupport'
|
23
21
|
|
24
22
|
s.add_development_dependency 'rails', '~> 3.0.0'
|
25
23
|
s.add_development_dependency 'sqlite3'
|
26
24
|
s.add_development_dependency 'bson_ext'
|
27
25
|
s.add_development_dependency 'mongoid', '~> 2.0.0'
|
26
|
+
s.add_development_dependency 'mongo_mapper','~>0.9.0'
|
28
27
|
s.add_development_dependency 'mocha'
|
29
28
|
s.add_development_dependency 'simple_form'
|
30
29
|
s.add_development_dependency 'formtastic'
|
@@ -1,5 +1,5 @@
|
|
1
1
|
/*!
|
2
|
-
* Rails 3 Client Side Validations - v3.0.
|
2
|
+
* Rails 3 Client Side Validations - v3.0.5
|
3
3
|
* https://github.com/bcardarlela/client_side_validations
|
4
4
|
*
|
5
5
|
* Copyright (c) 2011 Brian Cardarella
|
@@ -48,13 +48,15 @@
|
|
48
48
|
var confirmationElement = $(this),
|
49
49
|
element = form.find('#' + this.id.match(/(.+)_confirmation/)[1] + '[data-validate]:input');
|
50
50
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
51
|
+
if (element[0]) {
|
52
|
+
$('#' + confirmationElement.attr('id'))
|
53
|
+
.live('focusout', function() {
|
54
|
+
element.data('changed', true).isValid(settings.validators);
|
55
|
+
})
|
56
|
+
.live('keyup', function() {
|
57
|
+
element.data('changed', true).isValid(settings.validators);
|
58
|
+
})
|
59
|
+
}
|
58
60
|
});
|
59
61
|
|
60
62
|
var addError = function(element, message) {
|
@@ -127,7 +129,7 @@ var clientSideValidations = {
|
|
127
129
|
all: function() { return jQuery.extend({}, clientSideValidations.validators.local, clientSideValidations.validators.remote) },
|
128
130
|
local: {
|
129
131
|
presence: function(element, options) {
|
130
|
-
if (/^\s*$/.test(element.val())) {
|
132
|
+
if (/^\s*$/.test(element.val() || "")) {
|
131
133
|
return options.message;
|
132
134
|
}
|
133
135
|
},
|
@@ -171,7 +173,7 @@ var clientSideValidations = {
|
|
171
173
|
equal_to: '==', less_than: '<', less_than_or_equal_to: '<=' }
|
172
174
|
|
173
175
|
for (var check in CHECKS) {
|
174
|
-
if (options[check] && !(new Function("return " + element.val() + CHECKS[check] + options[check])())) {
|
176
|
+
if (options[check] != undefined && !(new Function("return " + element.val() + CHECKS[check] + options[check])())) {
|
175
177
|
return options.messages[check];
|
176
178
|
}
|
177
179
|
}
|
@@ -191,7 +193,7 @@ var clientSideValidations = {
|
|
191
193
|
} else if (options.minimum) {
|
192
194
|
blankOptions.message = options.messages.minimum;
|
193
195
|
}
|
194
|
-
if ((message = this.presence(element, blankOptions)) && options.allow_blank == true
|
196
|
+
if ((message = this.presence(element, blankOptions)) && options.allow_blank == true) {
|
195
197
|
return;
|
196
198
|
} else if (message) {
|
197
199
|
return message;
|
@@ -290,6 +292,11 @@ var clientSideValidations = {
|
|
290
292
|
} else {
|
291
293
|
var name = element.attr('name');
|
292
294
|
}
|
295
|
+
|
296
|
+
// Override the name if a nested module class is passed
|
297
|
+
if (options['class']) {
|
298
|
+
name = options['class'] + '[' + name.split('[')[1]
|
299
|
+
}
|
293
300
|
data[name] = element.val();
|
294
301
|
|
295
302
|
if (jQuery.ajax({
|
@@ -370,7 +377,14 @@ var clientSideValidations = {
|
|
370
377
|
var errorElement = wrapper.find('p.' + settings.inline_error_class);
|
371
378
|
errorElement.remove();
|
372
379
|
}
|
373
|
-
|
380
|
+
},
|
381
|
+
'NestedForm::Builder': {
|
382
|
+
add: function(element, settings, message) {
|
383
|
+
clientSideValidations.formBuilders['ActionView::Helpers::FormBuilder'].add(element, settings, message);
|
384
|
+
},
|
385
|
+
remove: function(element, settings, message) {
|
386
|
+
clientSideValidations.formBuilders['ActionView::Helpers::FormBuilder'].remove(element, settings, message);
|
387
|
+
}
|
374
388
|
}
|
375
389
|
},
|
376
390
|
callbacks: {
|
@@ -1,8 +1,10 @@
|
|
1
1
|
module ClientSideValidations
|
2
2
|
end
|
3
3
|
|
4
|
+
require 'client_side_validations/active_model' if defined?(::ActiveModel)
|
4
5
|
require 'client_side_validations/active_record' if defined?(::ActiveRecord)
|
5
6
|
require 'client_side_validations/mongoid' if defined?(::Mongoid)
|
7
|
+
require 'client_side_validations/mongo_mapper' if defined?(::MongoMapper)
|
6
8
|
require 'client_side_validations/action_view'
|
7
9
|
require 'client_side_validations/middleware' if defined?(::Rails)
|
8
10
|
|
@@ -27,7 +27,7 @@ module ClientSideValidations::ActionView::Helpers
|
|
27
27
|
def self.client_side_form_settings(options, form_helper)
|
28
28
|
{
|
29
29
|
:type => self.to_s,
|
30
|
-
:input_tag => form_helper.class.field_error_proc.call(%{<span id="input_tag" />},
|
30
|
+
:input_tag => form_helper.class.field_error_proc.call(%{<span id="input_tag" />}, Struct.new(:error_message, :tag_id).new([], "")),
|
31
31
|
:label_tag => form_helper.class.field_error_proc.call(%{<label id="label_tag" />}, Struct.new(:error_message, :tag_id).new([], ""))
|
32
32
|
}
|
33
33
|
end
|
@@ -80,17 +80,27 @@ module ClientSideValidations::ActionView::Helpers
|
|
80
80
|
def apply_client_side_validators(method, options = {})
|
81
81
|
if @options[:validate] && options[:validate] != false && validators = filter_validators(@object.client_side_validation_hash[method], options[:validate])
|
82
82
|
options.merge!("data-validate" => true)
|
83
|
-
@options[:validators].merge!("#{@object_name}[#{method}]" => validators)
|
83
|
+
@options[:validators].merge!("#{@object_name}[#{method}]#{options[:multiple] ? "[]" : nil}" => validators)
|
84
84
|
end
|
85
85
|
end
|
86
86
|
|
87
87
|
def filter_validators(validators, filters)
|
88
88
|
if validators
|
89
89
|
filtered_validators = validators.inject({}) do |filtered_validators, validator|
|
90
|
-
|
91
|
-
|
90
|
+
filtered_validators[validator.first] = validator.last
|
91
|
+
if has_filter_for_validator?(validator, filters)
|
92
|
+
if filter_validator?(validator, filters)
|
93
|
+
filtered_validators.delete(validator.first)
|
94
|
+
elsif force_validator_despite_conditional?(validator, filters) && !can_run_validator?(validator)
|
95
|
+
filtered_validators.delete(validator.first)
|
96
|
+
end
|
97
|
+
else
|
98
|
+
if validator.last.key?(:if) || validator.last.key?(:unless)
|
99
|
+
filtered_validators.delete(validator.first)
|
100
|
+
end
|
92
101
|
end
|
93
|
-
|
102
|
+
filtered_validators[validator.first].delete(:if) if filtered_validators[validator.first]
|
103
|
+
filtered_validators[validator.first].delete(:unless) if filtered_validators[validator.first]
|
94
104
|
filtered_validators
|
95
105
|
end
|
96
106
|
|
@@ -98,5 +108,45 @@ module ClientSideValidations::ActionView::Helpers
|
|
98
108
|
end
|
99
109
|
end
|
100
110
|
|
111
|
+
def has_filter_for_validator?(validator, filters)
|
112
|
+
filters && (filters == true || filters.key?(validator.first))
|
113
|
+
end
|
114
|
+
|
115
|
+
def filter_validator?(validator, filters)
|
116
|
+
filters != true && filters[validator.first] == false
|
117
|
+
end
|
118
|
+
|
119
|
+
def force_validator_despite_conditional?(validator, filters)
|
120
|
+
filters == true || filters[validator.first] == true
|
121
|
+
end
|
122
|
+
|
123
|
+
def can_run_validator?(validator)
|
124
|
+
result = true
|
125
|
+
if_result = can_run_if_validator?(validator.last[:if])
|
126
|
+
unless_result = can_run_unless_validator?(validator.last[:unless])
|
127
|
+
result = result && if_result unless if_result.nil?
|
128
|
+
result = result && unless_result unless unless_result.nil?
|
129
|
+
result
|
130
|
+
end
|
131
|
+
|
132
|
+
def can_run_if_validator?(conditional)
|
133
|
+
if conditional
|
134
|
+
if conditional.is_a?(Symbol)
|
135
|
+
!!@object.send(conditional)
|
136
|
+
else
|
137
|
+
!!conditional.call(@object)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def can_run_unless_validator?(conditional)
|
143
|
+
if conditional
|
144
|
+
if conditional.is_a?(Symbol)
|
145
|
+
!@object.send(conditional)
|
146
|
+
else
|
147
|
+
!conditional.call(@object)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
101
151
|
end
|
102
152
|
end
|
@@ -6,6 +6,8 @@ module ClientSideValidations::ActionView::Helpers
|
|
6
6
|
options = args.extract_options!
|
7
7
|
if options[:validate]
|
8
8
|
|
9
|
+
content_for_name = options[:validate] unless options[:validate] == true
|
10
|
+
|
9
11
|
# Always turn off HTML5 Validations
|
10
12
|
options[:html] ||= {}
|
11
13
|
options[:html][:novalidate] = true
|
@@ -26,7 +28,12 @@ module ClientSideValidations::ActionView::Helpers
|
|
26
28
|
form = super(record_or_name_or_array, *(args << options), &proc)
|
27
29
|
# Because of the load order requirement above this sub is necessary
|
28
30
|
# Would be nice to not do this
|
29
|
-
|
31
|
+
script = insert_validators_into_script(script)
|
32
|
+
if content_for_name
|
33
|
+
content_for(content_for_name) { script.html_safe }
|
34
|
+
script = nil
|
35
|
+
end
|
36
|
+
"#{form}#{script}".html_safe
|
30
37
|
end
|
31
38
|
|
32
39
|
def apply_form_for_options!(object_or_array, options)
|
@@ -42,6 +49,17 @@ module ClientSideValidations::ActionView::Helpers
|
|
42
49
|
|
43
50
|
private
|
44
51
|
|
52
|
+
def insert_validators_into_script(script)
|
53
|
+
# There is probably a more performant way of doing this
|
54
|
+
# But using String#sub has some issues. Undocumented "features"
|
55
|
+
if script
|
56
|
+
script = script.split(/"validator_hash"/)
|
57
|
+
script = "#{script[0]}#{@validators.to_json}#{script[1]}"
|
58
|
+
end
|
59
|
+
|
60
|
+
script
|
61
|
+
end
|
62
|
+
|
45
63
|
def client_side_form_settings(object, options)
|
46
64
|
if options[:validate]
|
47
65
|
builder = options[:builder] || ActionView::Base.default_form_builder
|
@@ -57,7 +75,7 @@ module ClientSideValidations::ActionView::Helpers
|
|
57
75
|
end
|
58
76
|
|
59
77
|
content_tag(:script) do
|
60
|
-
"
|
78
|
+
"window['#{var_name}'] = #{builder.client_side_form_settings(options, self).merge(:validators => 'validator_hash').to_json};".html_safe
|
61
79
|
end
|
62
80
|
|
63
81
|
end
|
@@ -4,8 +4,9 @@ module ClientSideValidations::ActiveModel
|
|
4
4
|
module Validator
|
5
5
|
|
6
6
|
def client_side_hash(model, attribute)
|
7
|
-
|
8
|
-
{ :message => model.errors.generate_message(attribute, message_type,
|
7
|
+
options = self.options.dup
|
8
|
+
{ :message => model.errors.generate_message(attribute, message_type, options) }.
|
9
|
+
merge(options.except(*::ActiveModel::Errors::CALLBACKS_OPTIONS - [:allow_blank, :if, :unless]))
|
9
10
|
end
|
10
11
|
|
11
12
|
private
|
@@ -17,26 +18,34 @@ module ClientSideValidations::ActiveModel
|
|
17
18
|
|
18
19
|
module Validations
|
19
20
|
def client_side_validation_hash
|
20
|
-
_validators.
|
21
|
+
@client_side_validation_hash ||= _validators.inject({}) do |attr_hash, attr|
|
22
|
+
unless [nil, :block].include?(attr[0])
|
23
|
+
|
24
|
+
validator_hash = attr[1].inject({}) do |kind_hash, validator|
|
25
|
+
client_side_hash = validator.client_side_hash(self, attr[0])
|
26
|
+
# Yeah yeah, #new_record? is not part of ActiveModel :p
|
27
|
+
if (can_use_for_client_side_validation?(client_side_hash, validator))
|
28
|
+
kind_hash.merge!(validator.kind => client_side_hash.except(:on))
|
29
|
+
else
|
30
|
+
kind_hash.merge!({})
|
31
|
+
end
|
32
|
+
end
|
21
33
|
|
22
|
-
|
23
|
-
|
24
|
-
# Yeah yeah, #new_record? is not part of ActiveModel :p
|
25
|
-
if (can_use_for_client_side_validation?(client_side_hash, validator))
|
26
|
-
kind_hash.merge!(validator.kind => client_side_hash.except(:on))
|
34
|
+
if validator_hash.present?
|
35
|
+
attr_hash.merge!(attr[0] => validator_hash)
|
27
36
|
else
|
28
|
-
|
37
|
+
attr_hash
|
29
38
|
end
|
39
|
+
else
|
40
|
+
attr_hash
|
30
41
|
end
|
31
|
-
|
32
|
-
attr_hash.merge!(attr[0] => validator_hash)
|
33
|
-
end.delete_if { |key, value| value.blank? }
|
42
|
+
end
|
34
43
|
end
|
35
44
|
|
36
45
|
private
|
37
46
|
|
38
47
|
def can_use_for_client_side_validation?(client_side_hash, validator)
|
39
|
-
((self.respond_to?(:new_record?) &&
|
48
|
+
((self.respond_to?(:new_record?) && validator.options[:on] == (self.new_record? ? :create : :update)) || validator.options[:on].nil?) && validator.kind != :block
|
40
49
|
end
|
41
50
|
end
|
42
51
|
end
|
@@ -2,19 +2,21 @@ module ClientSideValidations::ActiveModel
|
|
2
2
|
module Length
|
3
3
|
|
4
4
|
def client_side_hash(model, attribute)
|
5
|
-
|
5
|
+
options = self.options.dup
|
6
|
+
hash = { :messages => {} }
|
7
|
+
hash[:js_tokenizer] = options[:js_tokenizer] if options[:js_tokenizer]
|
8
|
+
hash[:allow_blank] = true if options[:allow_blank]
|
6
9
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
hash.merge!(key => model.errors.generate_message(attribute, self.class::MESSAGES[key], errors_options))
|
10
|
+
self.class::MESSAGES.each do |option, message_type|
|
11
|
+
if count = options[option]
|
12
|
+
options[:message] = options[message_type]
|
13
|
+
options.delete(:message) if options[:message].nil?
|
14
|
+
hash[:messages][option] = model.errors.generate_message(attribute, message_type, options.merge(:count => count))
|
15
|
+
hash[option] = count
|
16
|
+
end
|
15
17
|
end
|
16
18
|
|
17
|
-
|
19
|
+
hash
|
18
20
|
end
|
19
21
|
|
20
22
|
end
|
@@ -5,20 +5,25 @@ module ClientSideValidations::ActiveModel
|
|
5
5
|
|
6
6
|
def self.included(base)
|
7
7
|
OPTION_MAP.merge!(base::CHECKS.keys.inject({}) { |hash, key| hash.merge!(key => key) })
|
8
|
-
OPTION_MAP.merge!(:numericality => :not_a_number, :only_integer => :not_an_integer)
|
9
8
|
end
|
10
9
|
|
11
10
|
def client_side_hash(model, attribute)
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
11
|
+
options = self.options.dup
|
12
|
+
hash = { :messages => { :numericality => model.errors.generate_message(attribute, :not_a_number, options) } }
|
13
|
+
|
14
|
+
if options[:only_integer]
|
15
|
+
hash[:messages][:only_integer] = model.errors.generate_message(attribute, :not_an_integer, options)
|
16
|
+
hash[:only_integer] = true
|
17
|
+
end
|
18
|
+
|
19
|
+
OPTION_MAP.each do |option, message_type|
|
20
|
+
if count = options[option]
|
21
|
+
hash[:messages][option] = model.errors.generate_message(attribute, message_type, options.merge(:count => count))
|
22
|
+
hash[option] = count
|
23
|
+
end
|
19
24
|
end
|
20
25
|
|
21
|
-
|
26
|
+
hash
|
22
27
|
end
|
23
28
|
|
24
29
|
end
|
@@ -17,7 +17,11 @@ module ClientSideValidations::ActiveRecord
|
|
17
17
|
relation = t[attribute].matches(value)
|
18
18
|
end
|
19
19
|
|
20
|
-
|
20
|
+
if relation.is_a?(Arel::Nodes::SqlLiteral)
|
21
|
+
relation = Arel::Nodes::SqlLiteral.new("BINARY #{t[attribute].eq(value).to_sql} AND #{t.primary_key.not_eq(params[:id]).to_sql}")
|
22
|
+
else
|
23
|
+
relation = relation.and(t.primary_key.not_eq(params[:id])) if params[:id]
|
24
|
+
end
|
21
25
|
|
22
26
|
(params[:scope] || {}).each do |key, value|
|
23
27
|
relation = relation.and(t[key].eq(value))
|
@@ -1,16 +1,18 @@
|
|
1
1
|
module ClientSideValidations::ActiveRecord
|
2
2
|
module Uniqueness
|
3
3
|
def client_side_hash(model, attribute)
|
4
|
-
|
5
|
-
hash
|
6
|
-
hash =
|
7
|
-
|
8
|
-
if
|
9
|
-
hash[:scope] = Array.wrap(
|
4
|
+
hash = {}
|
5
|
+
hash[:message] = model.errors.generate_message(attribute, message_type, options.except(:scope))
|
6
|
+
hash[:case_sensitive] = options[:case_sensitive]
|
7
|
+
hash[:id] = model.id unless model.new_record?
|
8
|
+
if options.key?(:scope) && options[:scope].present?
|
9
|
+
hash[:scope] = Array.wrap(options[:scope]).inject({}) do |scope_hash, scope_item|
|
10
10
|
scope_hash.merge!(scope_item => model.send(scope_item))
|
11
11
|
end
|
12
|
-
|
13
|
-
|
12
|
+
end
|
13
|
+
|
14
|
+
unless model.class.name.demodulize == model.class.name
|
15
|
+
hash[:class] = model.class.name.underscore
|
14
16
|
end
|
15
17
|
|
16
18
|
hash
|
@@ -63,6 +63,8 @@ module ClientSideValidations
|
|
63
63
|
middleware_klass = ClientSideValidations::ActiveRecord::Middleware
|
64
64
|
elsif (defined?(::Mongoid::Document) && klass.included_modules.include?(::Mongoid::Document))
|
65
65
|
middleware_klass = ClientSideValidations::Mongoid::Middleware
|
66
|
+
elsif (defined?(::MongoMapper::Document) && klass.included_modules.include?(::MongoMapper::Document))
|
67
|
+
middleware_klass = ClientSideValidations::MongoMapper::Middleware
|
66
68
|
end
|
67
69
|
|
68
70
|
middleware_klass.is_unique?(klass, attribute, value, request.params)
|
@@ -0,0 +1,9 @@
|
|
1
|
+
require 'client_side_validations/active_model'
|
2
|
+
require 'client_side_validations/mongo_mapper/middleware'
|
3
|
+
|
4
|
+
%w{uniqueness}.each do |validator|
|
5
|
+
require "client_side_validations/mongo_mapper/#{validator}"
|
6
|
+
validator.capitalize!
|
7
|
+
eval "MongoMapper::Plugins::Validations::#{validator}Validator.send(:include, ClientSideValidations::MongoMapper::#{validator})"
|
8
|
+
end
|
9
|
+
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module ClientSideValidations::MongoMapper
|
2
|
+
class Middleware
|
3
|
+
|
4
|
+
# Still need to handle embedded documents
|
5
|
+
def self.is_unique?(klass, attribute, value, params)
|
6
|
+
if params[:case_sensitive] == 'false'
|
7
|
+
value = Regexp.new("^#{Regexp.escape(value.to_s)}$", Regexp::IGNORECASE)
|
8
|
+
end
|
9
|
+
|
10
|
+
criteria = klass.where(attribute => value)
|
11
|
+
criteria = criteria.where(:_id => {'$ne' => BSON::ObjectId(params[:id])}) if params[:id]
|
12
|
+
|
13
|
+
(params[:scope] || {}).each do |key, value|
|
14
|
+
criteria = criteria.where(key => value)
|
15
|
+
end
|
16
|
+
|
17
|
+
!criteria.exists?
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|