client_side_validations 3.0.4 → 3.0.5
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/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
|