validatious-on-rails 0.4.5 → 0.4.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (33) hide show
  1. data/generators/validatious/templates/v2.rails.js +35 -0
  2. data/lib/validatious-on-rails/model_validations.rb +45 -32
  3. data/lib/validatious-on-rails/validatious/client_side_validator.rb +1 -1
  4. data/lib/validatious-on-rails/validatious/remote_validator.rb +4 -6
  5. data/lib/validatious-on-rails/validatious/validator.rb +48 -55
  6. data/lib/validatious-on-rails/validatious/validators/acceptance_accept_validator.rb +24 -0
  7. data/lib/validatious-on-rails/validatious/validators/confirmation_of_validator.rb +22 -0
  8. data/lib/validatious-on-rails/validatious/validators/exclusion_in_validator.rb +30 -0
  9. data/lib/validatious-on-rails/validatious/validators/format_with_validator.rb +27 -0
  10. data/lib/validatious-on-rails/validatious/validators/inclusion_in_validator.rb +30 -0
  11. data/lib/validatious-on-rails/validatious/validators/length/is_validator.rb +7 -10
  12. data/lib/validatious-on-rails/validatious/validators/length/maximum_validator.rb +6 -9
  13. data/lib/validatious-on-rails/validatious/validators/length/minimum_validator.rb +6 -9
  14. data/lib/validatious-on-rails/validatious/validators/numericality/equal_to_validator.rb +5 -7
  15. data/lib/validatious-on-rails/validatious/validators/numericality/even_validator.rb +5 -6
  16. data/lib/validatious-on-rails/validatious/validators/numericality/greater_than_or_equal_to_validator.rb +5 -7
  17. data/lib/validatious-on-rails/validatious/validators/numericality/greater_than_validator.rb +5 -7
  18. data/lib/validatious-on-rails/validatious/validators/numericality/less_than_or_equal_to_validator.rb +5 -7
  19. data/lib/validatious-on-rails/validatious/validators/numericality/less_than_validator.rb +5 -7
  20. data/lib/validatious-on-rails/validatious/validators/numericality/odd_validator.rb +5 -6
  21. data/lib/validatious-on-rails/validatious/validators/numericality/only_integer_validator.rb +6 -7
  22. data/lib/validatious-on-rails/validatious/validators/presence_validator.rb +4 -7
  23. data/lib/validatious-on-rails/validatious/validators/uniqueness_validator.rb +3 -10
  24. data/test/validatious_on_rails/controller_test.rb +1 -1
  25. data/test/validatious_on_rails/model_validations_test.rb +19 -19
  26. data/test/validatious_on_rails/rails/action_view_helpers_test.rb +11 -9
  27. data/test/validatious_on_rails/validatious/validator_test.rb +11 -11
  28. metadata +12 -12
  29. data/lib/validatious-on-rails/validatious/validators/acceptance_validator.rb +0 -28
  30. data/lib/validatious-on-rails/validatious/validators/confirmation_validator.rb +0 -23
  31. data/lib/validatious-on-rails/validatious/validators/exclusion_validator.rb +0 -28
  32. data/lib/validatious-on-rails/validatious/validators/format_validator.rb +0 -33
  33. data/lib/validatious-on-rails/validatious/validators/inclusion_validator.rb +0 -28
@@ -4,8 +4,43 @@
4
4
 
5
5
  if (typeof v2.Rails === 'undefined' || v2.Rails === null) {
6
6
  v2.Rails = {};
7
+ v2.Rails.params = {};
8
+ v2.Rails.messages = {};
7
9
  }
8
10
 
11
+ /**
12
+ * Checks if a string is blank (or undefined).
13
+ */
14
+ v2.blank = function blank(value) {
15
+ return v2.empty(value) || /^[\s\t\n]*$/.test(value);
16
+ };
17
+
18
+ /**
19
+ * Checks if a string is blank (or undefined).
20
+ */
21
+ v2.bool = function bool(value) {
22
+ value += '';
23
+ return (value === true) || (value === 'true');
24
+ };
25
+
26
+ /**
27
+ * Trim value - fast implementation.
28
+ */
29
+ v2.trim = function trim(value) {
30
+ var str = value.replace(/^\s\s*/, ''), ws = /\s/, i = str.length;
31
+ while (ws.test(str.charAt(--i)));
32
+ return str.slice(0, i + 1);
33
+ };
34
+
35
+ /**
36
+ * Trim Field elements and their values.
37
+ */
38
+ v2.trimField = function trimField(field) {
39
+ for (var i = 0; i < field.__elements.length; i++) {
40
+ field.__elements[i].value = v2.trim(field.__elements[i].value);
41
+ };
42
+ };
43
+
9
44
  /**
10
45
  * Generic validator that acts as a client-side validator/helper for remote validator responses.
11
46
  */
@@ -129,8 +129,10 @@ module ValidatiousOnRails
129
129
  #
130
130
  def acceptance_of(validation)
131
131
  validators = []
132
+ validation.options[:allow_nil] = false if validation.options[:allow_nil].nil?
132
133
  validation.options[:accept] ||= '1' # Rails default.
133
- validators << Validatious::AcceptanceValidator.new(validation, validation.options[:accept])
134
+ validators << Validatious::AcceptanceAcceptValidator.new(validation.options[:accept],
135
+ validation.options[:allow_nil])
134
136
  end
135
137
 
136
138
  # Resolve validation from validates_associated.
@@ -145,22 +147,19 @@ module ValidatiousOnRails
145
147
  # This validation is treated a bit differently in compare
146
148
  # to the other validations. See "from_active_record".
147
149
  #
148
- # TODO: Message should be Rails I18n message, not Validatious.
149
- #
150
150
  # NOTE: Not supported:
151
- # * :message - TODO: Explicit or Rails I18n/default message.
152
151
  # * :on - TODO.
153
152
  # * :if/:unless - hard to port all to client-side JavaScript
154
153
  # (impossible: procs, unaccessible valiables, etc.).
155
154
  #
156
155
  def confirmation_of(validation)
157
156
  validators = []
158
- arg = unless validation.active_record.present?
157
+ field_id = unless validation.active_record.present?
159
158
  "#{validation.active_record.name.tableize.singularize.gsub('/', '_')}_#{validation.name}"
160
159
  else
161
160
  "#{validation.name}"
162
161
  end
163
- validators << Validatious::ConfirmationValidator.new(validation, arg)
162
+ validators << Validatious::ConfirmationOfValidator.new(field_id)
164
163
  end
165
164
 
166
165
  # Resolve validation from validates_exclusion_of.
@@ -174,7 +173,10 @@ module ValidatiousOnRails
174
173
  #
175
174
  def exclusion_of(validation)
176
175
  validators = []
177
- validators << Validatious::ExclusionValidator.new(validation)
176
+ validation.options[:allow_nil] = false if validation.options[:allow_nil].nil?
177
+ validation.options[:allow_blank] = false if validation.options[:allow_blank].nil?
178
+ validators << Validatious::ExclusionInValidator.new(validation.options[:in],
179
+ validation.options[:allow_nil], validation.options[:allow_blank])
178
180
  end
179
181
 
180
182
  # Resolve validation from validates_format_of.
@@ -189,7 +191,10 @@ module ValidatiousOnRails
189
191
  #
190
192
  def format_of(validation)
191
193
  validators = []
192
- validators << Validatious::FormatValidator.new(validation)
194
+ validation.options[:allow_nil] = false if validation.options[:allow_nil].nil?
195
+ validation.options[:allow_blank] = false if validation.options[:allow_blank].nil?
196
+ validators << Validatious::FormatWithValidator.new(validation.options[:with],
197
+ validation.options[:allow_nil], validation.options[:allow_blank])
193
198
  end
194
199
 
195
200
  # Resolve validation from validates_inclusion_of.
@@ -203,7 +208,10 @@ module ValidatiousOnRails
203
208
  #
204
209
  def inclusion_of(validation)
205
210
  validators = []
206
- validators << Validatious::InclusionValidator.new(validation)
211
+ validation.options[:allow_nil] = false if validation.options[:allow_nil].nil?
212
+ validation.options[:allow_blank] = false if validation.options[:allow_blank].nil?
213
+ validators << Validatious::InclusionInValidator.new(validation.options[:in],
214
+ validation.options[:allow_nil], validation.options[:allow_blank])
207
215
  end
208
216
 
209
217
  # Resolve validation from validates_length_of.
@@ -219,23 +227,30 @@ module ValidatiousOnRails
219
227
  #
220
228
  def length_of(validation)
221
229
  validators = []
230
+ validation.options[:allow_nil] = false if validation.options[:allow_nil].nil?
231
+ validation.options[:allow_blank] = false if validation.options[:allow_blank].nil?
222
232
 
223
233
  if validation.options[:is].present?
224
- validators << Validatious::Length::IsValidator.new(validation, validation.options[:is])
234
+ validators << Validatious::Length::IsValidator.new(validation.options[:is],
235
+ (validation.options[:allow_nil] || false),
236
+ (validation.options[:allow_blank] || false))
225
237
  elsif [:in, :within, :minimum, :maximum].any? { |k| validation.options[k].present? }
226
238
  validation.options[:within] ||= validation.options[:in]
227
239
  validation.options[:minimum] ||= validation.options[:within].min rescue nil
228
240
  validation.options[:maximum] ||= validation.options[:within].max rescue nil
229
241
 
230
242
  if validation.options[:minimum].present?
231
- validators << Validatious::Length::MinimumValidator.new(validation, validation.options[:minimum])
243
+ validators << Validatious::Length::MinimumValidator.new(validation.options[:minimum],
244
+ (validation.options[:allow_nil] || false),
245
+ (validation.options[:allow_blank] || false))
232
246
  end
233
247
 
234
248
  if validation.options[:maximum].present?
235
- validators << Validatious::Length::MaximumValidator.new(validation, validation.options[:maximum])
249
+ validators << Validatious::Length::MaximumValidator.new(validation.options[:maximum],
250
+ (validation.options[:allow_nil] || false),
251
+ (validation.options[:allow_blank] || false))
236
252
  end
237
253
  end
238
-
239
254
  validators
240
255
  end
241
256
  alias :size_of :length_of
@@ -252,22 +267,28 @@ module ValidatiousOnRails
252
267
  #
253
268
  def numericality_of(validation)
254
269
  validators = []
270
+ validation.options[:allow_nil] = false if validation.options[:allow_nil].nil?
255
271
 
256
272
  if validation.options[:odd] && !validation.options[:even]
257
- validators << Validatious::Numericality::OddValidator.new(validation)
273
+ validators << Validatious::Numericality::OddValidator.new(validation.options[:allow_nil])
258
274
  end
259
275
 
260
276
  if validation.options[:even] && !validation.options[:odd]
261
- validators << Validatious::Numericality::EvenValidator.new(validation)
277
+ validators << Validatious::Numericality::EvenValidator.new(validation.options[:allow_nil])
262
278
  end
263
279
 
264
- (validation.options.keys & [:only_integer, :equal_to, :less_than, :less_than_or_equal_to,
265
- :greater_than, :greater_than_or_equal_to]).each { |v|
266
- validator_klass = "::ValidatiousOnRails::Validatious::Numericality::#{v.to_s.classify}Validator".constantize
267
- value = validation.options[v] if validation.options[v].is_a?(::Numeric)
268
- validators << validator_klass.new(validation, value)
269
- }
280
+ if validation.options[:only_integer]
281
+ validators << Validatious::Numericality::OnlyIntegerValidator.new(validation.options[:allow_nil])
282
+ end
270
283
 
284
+ (validation.options.keys & [:equal_to, :less_than, :less_than_or_equal_to,
285
+ :greater_than, :greater_than_or_equal_to]).each { |name|
286
+ validator_klass = "::ValidatiousOnRails::Validatious::Numericality::#{name.to_s.classify}Validator".constantize
287
+ value = validation.options[name]
288
+ if value.is_a?(::Numeric)
289
+ validators << validator_klass.new(validation.options[name], validation.options[:allow_nil])
290
+ end
291
+ }
271
292
  validators
272
293
  end
273
294
 
@@ -282,32 +303,24 @@ module ValidatiousOnRails
282
303
  #
283
304
  def presence_of(validation)
284
305
  validators = []
285
- validators << Validatious::PresenceValidator.new(validation)
306
+ validators << Validatious::PresenceValidator.new
286
307
  end
287
308
 
288
309
  # Resolve validation from validates_uniqueness_of.
289
310
  #
290
- # TODO: Implement using RemoteValidator.
291
- #
292
311
  def uniqueness_of(validation)
293
312
  validators = []
294
- validators << Validatious::UniquenessValidator.new(validation)
313
+ validators << Validatious::UniquenessValidator.new
295
314
  end
296
315
 
297
316
  # Unknown validations - if no matching custom validator is found/registered.
298
317
  #
299
318
  def method_missing(sym, *args, &block)
300
319
  ::ValidatiousOnRails.log "Unknown validation: #{sym}." <<
301
- " No custom Validatious validator found for this validation makro. " <<
302
- "Maybe you forgot to register you custom validation using: " <<
303
- "ValidatiousOnRails::ModelValidations.add(<CustomValidationClass>)", :warn
320
+ " No custom Validatious validator found for this validation makro. ", :warn
304
321
  nil
305
322
  end
306
323
 
307
- # TODO: Include custom validations here...
308
- #
309
- # @custom_validators.each { |validator_class| ... }
310
-
311
324
  end
312
325
  end
313
326
  end
@@ -5,7 +5,7 @@ module ValidatiousOnRails
5
5
  module Validatious
6
6
  class ClientSideValidator < Validator
7
7
 
8
- def initialize(name, *args)
8
+ def initialize(*args)
9
9
  super
10
10
  end
11
11
 
@@ -5,16 +5,14 @@ module ValidatiousOnRails
5
5
  module Validatious
6
6
  class RemoteValidator < Validator
7
7
 
8
- def initialize(validation, *args)
9
- name = self.class.name.split('::').last.underscore.gsub(/_validator$/, '')
10
- super name, *args
11
- self.message = self.class.generate_message(validation)
8
+ def initialize(*args)
9
+ super
12
10
  end
13
11
 
14
12
  # Override default Validator-fn, with default a RemoteValidator-fn.
15
13
  #
16
14
  # 1. Perform AJAX request (dependencies: validatious-on-rails.js, XMLHttpRequest.js).
17
- # 2. Always return true, callback-function should perform the actual client side validation.
15
+ # 2. Always return last result, callback-function should perform the actual client side validation.
18
16
  #
19
17
  def fn
20
18
  self.class.truncate_whitespace(@fn ||= %{
@@ -43,7 +41,7 @@ module ValidatiousOnRails
43
41
  return true if record.errors[attribute_name.to_sym].blank?
44
42
 
45
43
  # TODO: Refactor this when "the better" namin convention is used (see TODO).
46
- validation_macro = ("validates_%s" % self.name.split('::').last.underscore.gsub(/_validator$/, ''))
44
+ validation_macro = ("validates_%s" % self.generic_name)
47
45
  validation = record.class.reflect_on_validations_for(attribute_name.to_sym).select { |v|
48
46
  v.macro.to_s == validation_macro || v.macro.to_s == "#{validation_macro}_of"
49
47
  }.first
@@ -30,15 +30,16 @@ module ValidatiousOnRails
30
30
  :aliases,
31
31
  :accept_empty,
32
32
  :fn,
33
- :args
34
-
35
- def initialize(name, *args)
36
- raise ValidatorError, "Parameter :name is required for an Validatious validator" unless name.present?
37
- self.name = name
33
+ :args,
34
+ :data
35
+
36
+ def initialize(*args)
37
+ self.name = self.class.generic_name
38
38
  options = args.extract_options!
39
39
  options.each do |attr, value|
40
40
  self.send(:"#{attr}=", value) if value.present?
41
41
  end
42
+ self.accept_empty = false
42
43
  self.args = args
43
44
  end
44
45
 
@@ -85,16 +86,21 @@ module ValidatiousOnRails
85
86
  @aliases ||= []
86
87
  end
87
88
 
88
-
89
89
  # Decides if the validator should pass (return true) when the value is empty.
90
90
  # This is usually a good idea because you can leave it up to the required validator
91
91
  # to specifically check for emptiness. One benefit of this approach is more
92
92
  # fine grained error reporting, helping the user.
93
93
  #
94
- # Default value is: true.
94
+ # Default value is: false. Rails default (:allow_nil).
95
95
  #
96
96
  def accept_empty
97
- @accept_empty.nil? ? true : @accept_empty
97
+ @accept_empty.nil? ? false : @accept_empty
98
+ end
99
+
100
+ # TODO: Doc.
101
+ #
102
+ def data
103
+ @data ||= ''
98
104
  end
99
105
 
100
106
  # This is the method that performs the validation. It receives three arguments,
@@ -139,9 +145,10 @@ module ValidatiousOnRails
139
145
  # - hash ordered by key only 1.9. ='(
140
146
  js_options = options.keys.collect(&:to_s).sort.collect { |k|
141
147
  v = options[k.to_sym]
142
- ("#{k}: #{k.to_sym == :fn ? v : v.to_json}" if [false, true].include?(v) || v.present?)
148
+ (("#{k}: #{k.to_sym == :fn ? v : v.to_json}") unless v.blank? && v != false)
143
149
  }.compact.join(',')
144
- self.class.truncate_whitespace("v2.Validator.add({#{js_options}});")
150
+ js = self.class.truncate_whitespace(self.data)
151
+ js << self.class.truncate_whitespace("\nv2.Validator.add({#{js_options}});")
145
152
  end
146
153
  alias :to_s :to_js
147
154
 
@@ -159,15 +166,26 @@ module ValidatiousOnRails
159
166
  string.gsub(/[\n]+[\s]+/, '')
160
167
  end
161
168
 
162
- def validate_blank(allow_blank)
169
+ def handle_nil(index = 1)
163
170
  %{
164
- var isBlank = /^[#{'\s\t\n'}]*$/.test(value);
165
- if (#{allow_blank == true} && isBlank) {
171
+ if (v2.bool(params[#{index}]) && v2.empty(value)) {
166
172
  return true;
167
173
  };
168
174
  }
169
175
  end
170
176
 
177
+ def handle_blank(index = 2)
178
+ %{
179
+ if (v2.bool(params[#{index}]) && v2.blank(value)) {
180
+ return true;
181
+ };
182
+ if (!v2.bool(params[#{index}])) {
183
+ v2.trimField(field);
184
+ value = v2.trim(value);
185
+ };
186
+ }
187
+ end
188
+
171
189
  # Generate a unique valdiator ID to avoid clashes.
172
190
  # Note: Ruby #hash is way faster than SHA1 (etc.) - just replace any negative sign.
173
191
  #
@@ -175,58 +193,33 @@ module ValidatiousOnRails
175
193
  value.to_s.hash.to_s.tr('-', '1')
176
194
  end
177
195
 
178
- # Any named specified for this custom validation?
179
- # E.g. validates_format_of :name, :with => /\d{6}-\d{4}/, :name => 'ssn-se'
180
- #
181
- # If not, create one that's uniqe based on validation and what to validate based on,
182
- # e.g. validates_format_of :name, :with => /\d{6}-\d{4}/ # => :name => "format_with_#{hash-of-:with-value}"
183
- #
184
- def generate_name(validation, id_key, id_value = nil)
185
- # Avoiding duplicates...
186
- identifier = "-#{id_value}" if id_value.present?
187
- validator_id = "#{validation.macro.to_s.sub(/^validates_/, '').sub(/_of/, '')}_#{id_key}#{identifier}"
188
- name = validation.options[:name].present? ? validation.options[:name] : validator_id
189
- # "_" is not allowed in name/alias(es) - used to seperate validator-id from it's args/params.
190
- [name, validator_id].collect! { |v| v.tr('_', '-') }
191
- end
192
-
193
196
  # Generate proper error message using explicit message, or I18n-lookup.
194
197
  # Core validations gets treated by Rails - unless explicit message is set that is.
195
198
  #
196
- def generate_message(*args)
197
- options = args.extract_options!
198
- validation = args.shift if args.first.is_a?(::ActiveRecord::Reflection::MacroReflection)
199
- explicit_message = validation.options[:message] if validation
200
- key = options.delete(:key) || (explicit_message if explicit_message.is_a?(::Symbol))
201
-
202
- message = if key.present?
203
- ::I18n.t(key, options.merge(:scope => :'activerecord.errors.messages',
204
- :default => "activerecord.errors.messages.#{key}"))
205
- elsif explicit_message.is_a?(::String)
206
- explicit_message
207
- elsif validation.present?
208
- unless ::ValidatiousOnRails::ModelValidations::CORE_VALIDATIONS.include?(validation.macro.to_sym)
209
- # No core validation, try to make up a descent I18n lookup path using conventions.
210
- key ||= validation.macro.to_s.tr('-', '_').gsub(/^validates?_/, '').gsub(/_of/, '').to_sym
211
- ::I18n.t(key, options.merge(:scope => :'activerecord.errors.messages',
212
- :default => "activerecord.errors.messages.#{key}"))
213
- else
214
- # Nothing - let Rails rails handle the core validation message translations (I18n).
215
- end
216
- end
199
+ def generate_message(key_or_value, options = {})
200
+ message = case true
201
+ when key_or_value.is_a?(::String)
202
+ # Explicit message.
203
+ key_or_value
204
+ when key_or_value.is_a?(::Symbol)
205
+ # Lookup message with I18n key.
206
+ ::I18n.t(key_or_value, options.merge(:scope => :'activerecord.errors.messages',
207
+ :default => "activerecord.errors.messages.#{key_or_value}"))
208
+ end
217
209
  # Rails I18n interpolations => Validatious interpolations
218
210
  # Example: {{count}} => ${count}
219
- message.gsub(/\{\{/, '${').gsub(/\}\}/, '}')
211
+ message.to_s.gsub(/\{\{/, '${').gsub(/\}\}/, '}')
220
212
  end
221
213
 
222
- end
223
-
224
- protected
225
-
226
214
  def generic_name
227
- self.class.name.split('::').last.underscore.gsub(/_validator$/, '')
215
+ namespace = self.name.split('::')
216
+ name = []
217
+ name.unshift(namespace.pop) until namespace.blank? || namespace.last == 'Validatious'
218
+ name.join('-').underscore.gsub(/_validator$/, '').tr('_', '-')
228
219
  end
229
220
 
221
+ end
222
+
230
223
  end
231
224
  end
232
225
  end
@@ -0,0 +1,24 @@
1
+ # encoding: utf-8
2
+ require File.expand_path(File.join(File.dirname(__FILE__), *%w[.. validator]))
3
+
4
+ module ValidatiousOnRails
5
+ module Validatious
6
+ class AcceptanceAcceptValidator < ClientSideValidator
7
+
8
+ def initialize(*args)
9
+ super
10
+ self.message = self.class.generate_message(:accepted)
11
+ self.params = %w[accept allow_nil]
12
+ self.fn = %{
13
+ #{self.class.handle_nil(1)}
14
+ var accept_value = params[0] + '';
15
+ if (accept_value == 'true' || accept_value == 'false') {
16
+ accept_value = v2.bool(accept_value)
17
+ };
18
+ return value == accept_value;
19
+ }
20
+ end
21
+
22
+ end
23
+ end
24
+ end