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.
Files changed (53) hide show
  1. data/client_side_validations.gemspec +2 -3
  2. data/javascript/rails.validations.js +26 -12
  3. data/lib/client_side_validations.rb +2 -0
  4. data/lib/client_side_validations/action_view/form_builder.rb +55 -5
  5. data/lib/client_side_validations/action_view/form_helper.rb +20 -2
  6. data/lib/client_side_validations/active_model.rb +22 -13
  7. data/lib/client_side_validations/active_model/length.rb +12 -10
  8. data/lib/client_side_validations/active_model/numericality.rb +14 -9
  9. data/lib/client_side_validations/active_record/middleware.rb +5 -1
  10. data/lib/client_side_validations/active_record/uniqueness.rb +10 -8
  11. data/lib/client_side_validations/middleware.rb +2 -0
  12. data/lib/client_side_validations/mongo_mapper.rb +9 -0
  13. data/lib/client_side_validations/mongo_mapper/middleware.rb +20 -0
  14. data/lib/client_side_validations/mongo_mapper/uniqueness.rb +28 -0
  15. data/lib/client_side_validations/mongoid/uniqueness.rb +10 -8
  16. data/lib/client_side_validations/version.rb +1 -1
  17. data/test/action_view/cases/helper.rb +7 -1
  18. data/test/action_view/cases/test_helpers.rb +263 -0
  19. data/test/action_view/cases/test_legacy_helpers.rb +11 -0
  20. data/test/active_model/cases/test_validations.rb +21 -8
  21. data/test/active_record/cases/test_middleware.rb +25 -0
  22. data/test/active_record/cases/test_uniqueness_validator.rb +5 -0
  23. data/test/active_record/models/user.rb +4 -0
  24. data/test/formtastic/cases/test_form_helper.rb +1 -1
  25. data/test/javascript/public/test/callbacks/elementAfter.js +1 -1
  26. data/test/javascript/public/test/callbacks/elementBefore.js +1 -1
  27. data/test/javascript/public/test/callbacks/elementFail.js +1 -1
  28. data/test/javascript/public/test/callbacks/elementPass.js +1 -1
  29. data/test/javascript/public/test/callbacks/formAfter.js +1 -1
  30. data/test/javascript/public/test/callbacks/formBefore.js +1 -1
  31. data/test/javascript/public/test/callbacks/formFail.js +1 -1
  32. data/test/javascript/public/test/callbacks/formPass.js +1 -1
  33. data/test/javascript/public/test/form_builders/validateForm.js +1 -1
  34. data/test/javascript/public/test/form_builders/validateFormtastic.js +1 -1
  35. data/test/javascript/public/test/form_builders/validateNestedForm.js +66 -0
  36. data/test/javascript/public/test/form_builders/validateSimpleForm.js +1 -1
  37. data/test/javascript/public/test/validateElement.js +36 -1
  38. data/test/javascript/public/test/validators/length.js +7 -1
  39. data/test/javascript/public/test/validators/numericality.js +7 -0
  40. data/test/javascript/public/test/validators/presence.js +6 -0
  41. data/test/javascript/public/test/validators/uniqueness.js +8 -1
  42. data/test/javascript/server.rb +7 -1
  43. data/test/javascript/views/index.erb +1 -1
  44. data/test/mongo_mapper/cases/helper.rb +9 -0
  45. data/test/mongo_mapper/cases/test_base.rb +15 -0
  46. data/test/mongo_mapper/cases/test_middleware.rb +77 -0
  47. data/test/mongo_mapper/cases/test_uniqueness_validator.rb +50 -0
  48. data/test/mongo_mapper/models/magazine.rb +11 -0
  49. data/test/mongoid/cases/test_middleware.rb +9 -0
  50. data/test/mongoid/cases/test_uniqueness_validator.rb +5 -0
  51. data/test/mongoid/models/book.rb +4 -0
  52. data/test/simple_form/cases/test_form_helper.rb +1 -1
  53. 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', '~> 3.0.0'
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.1
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
- $('#' + confirmationElement.attr('id'))
52
- .live('focusout', function() {
53
- element.data('changed', true).isValid(settings.validators);
54
- })
55
- .live('keyup', function() {
56
- element.data('changed', true).isValid(settings.validators);
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 && !options.maximum) {
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" />}, Struct.new(:error_message, :tag_id).new([], "")),
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
- unless filters && filters.key?(validator.first) && !filters[validator.first]
91
- filtered_validators[validator.first] = validator.last
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
- "#{form}#{script ? script.sub('"validator_hash"', @validators.to_json) : nil}".html_safe
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
- "var #{var_name} = #{builder.client_side_form_settings(options, self).merge(:validators => 'validator_hash').to_json};".html_safe
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
- extra_options = options.except(*::ActiveModel::Errors::CALLBACKS_OPTIONS - [:on, :allow_blank])
8
- { :message => model.errors.generate_message(attribute, message_type, extra_options) }.merge(extra_options)
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.except(nil, :block).inject({}) do |attr_hash, attr|
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
- validator_hash = attr[1].inject({}) do |kind_hash, validator|
23
- client_side_hash = validator.client_side_hash(self, attr[0])
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
- kind_hash.merge!({})
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?) && client_side_hash[:on] == (self.new_record? ? :create : :update)) || client_side_hash[:on].nil?) && !validator.options.key?(:if) && !validator.options.key?(:unless) && validator.kind != :block
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
- extra_options = options.except(*::ActiveModel::Errors::CALLBACKS_OPTIONS - [:allow_blank, :on]).except(:tokenizer, :too_long, :too_short, :wrong_length)
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
- errors_options = options.except(*self.class::RESERVED_OPTIONS)
8
- messages = extra_options.except(:js_tokenizer, :allow_blank, :on).keys.inject({}) do |hash, key|
9
- errors_options[:count] = extra_options[key]
10
- count = extra_options[key]
11
- default_message = options[self.class::MESSAGES[key]]
12
- errors_options[:message] ||= default_message if default_message
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
- { :messages => messages }.merge(extra_options)
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
- except_options = ::ActiveModel::Errors::CALLBACKS_OPTIONS - [:on] + [:message]
13
- extra_options = options.except(*except_options).reject { |key, value| key == :only_integer && !value }
14
- keys = [:numericality] | (extra_options.keys - [:message, :on])
15
- filtered_options = options.except(*self.class::RESERVED_OPTIONS)
16
- messages = keys.inject({}) do |hash, key|
17
- count = extra_options[key]
18
- hash.merge!(key => model.errors.generate_message(attribute, OPTION_MAP[key], filtered_options.merge(:count => count)))
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
- { :messages => messages }.merge(extra_options)
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
- relation = relation.and(t.primary_key.not_eq(params[:id])) if params[:id]
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
- extra_options = options.except(*::ActiveModel::Errors::CALLBACKS_OPTIONS - [:on, :allow_blank])
5
- hash = { :message => model.errors.generate_message(attribute, message_type, extra_options.except(:case_sensitive, :scope)) }
6
- hash = hash.merge(extra_options).merge(model.new_record? ? {} : { :id => model.id })
7
-
8
- if hash[:scope].present?
9
- hash[:scope] = Array.wrap(hash[:scope]).inject({}) do |scope_hash, scope_item|
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
- else
13
- hash.delete(:scope)
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