validatious-on-rails 0.4.5 → 0.4.6

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.
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