judge 1.4.0 → 1.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/judge.gemspec +1 -1
- data/lib/generators/judge/templates/judge.js +2 -2
- data/lib/generators/judge/templates/underscore.js +121 -60
- data/lib/judge.rb +2 -1
- data/lib/judge/each_validator.rb +21 -0
- data/lib/judge/message_collection.rb +47 -56
- data/lib/judge/message_config.rb +41 -0
- data/lib/judge/validator.rb +10 -7
- data/lib/judge/validator_collection.rb +2 -4
- data/lib/judge/version.rb +1 -1
- data/spec/each_validator_spec.rb +17 -0
- data/spec/form_builder_spec.rb +1 -1
- data/spec/html_spec.rb +1 -1
- data/spec/javascripts/helpers/underscore.js +121 -60
- data/spec/message_collection_spec.rb +30 -41
- data/spec/setup.rb +6 -1
- data/spec/{factories.rb → support/factories.rb} +0 -0
- data/spec/support/locale/en.yml +18 -0
- data/spec/support/setup.rb +72 -0
- data/spec/{spec_helper.rb → support/spec_helper.rb} +2 -2
- data/spec/support/validators/city_validator.rb +9 -0
- data/spec/validator_collection_spec.rb +1 -1
- data/spec/validator_spec.rb +2 -6
- metadata +30 -20
data/judge.gemspec
CHANGED
@@ -18,6 +18,6 @@ Gem::Specification.new do |s|
|
|
18
18
|
s.add_development_dependency "jasmine", "~> 1.1.2"
|
19
19
|
s.add_development_dependency "rails", "~> 3.2"
|
20
20
|
s.add_development_dependency "rspec", "~> 2.8"
|
21
|
-
s.add_development_dependency "sqlite3
|
21
|
+
s.add_development_dependency "sqlite3", "~> 1.3.5"
|
22
22
|
s.add_development_dependency "factory_girl", "~> 2.6"
|
23
23
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
// Judge 1.
|
1
|
+
// Judge 1.5.0
|
2
2
|
// (c) 2011–2012 Joe Corcoran
|
3
3
|
// http://raw.github.com/joecorcoran/judge/master/LICENSE.txt
|
4
4
|
// This is the JavaScript part of Judge, a client-side validation gem for Rails 3.
|
@@ -13,7 +13,7 @@
|
|
13
13
|
// The judge namespace.
|
14
14
|
var judge = {};
|
15
15
|
|
16
|
-
judge.VERSION = '1.
|
16
|
+
judge.VERSION = '1.5.0';
|
17
17
|
|
18
18
|
// A judge.Watcher is a DOM element wrapper that judge uses to store validation info and instance methods.
|
19
19
|
judge.Watcher = function (element) {
|
@@ -1,4 +1,5 @@
|
|
1
|
-
|
1
|
+
|
2
|
+
// Underscore.js 1.3.2
|
2
3
|
// (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc.
|
3
4
|
// Underscore is freely distributable under the MIT license.
|
4
5
|
// Portions of Underscore are inspired or borrowed from Prototype,
|
@@ -62,7 +63,7 @@
|
|
62
63
|
}
|
63
64
|
|
64
65
|
// Current version.
|
65
|
-
_.VERSION = '1.3.
|
66
|
+
_.VERSION = '1.3.2';
|
66
67
|
|
67
68
|
// Collection Functions
|
68
69
|
// --------------------
|
@@ -180,7 +181,7 @@
|
|
180
181
|
each(obj, function(value, index, list) {
|
181
182
|
if (!(result = result && iterator.call(context, value, index, list))) return breaker;
|
182
183
|
});
|
183
|
-
return result;
|
184
|
+
return !!result;
|
184
185
|
};
|
185
186
|
|
186
187
|
// Determine if at least one element in the object matches a truth test.
|
@@ -224,7 +225,7 @@
|
|
224
225
|
|
225
226
|
// Return the maximum element or (element-based computation).
|
226
227
|
_.max = function(obj, iterator, context) {
|
227
|
-
if (!iterator && _.isArray(obj)) return Math.max.apply(Math, obj);
|
228
|
+
if (!iterator && _.isArray(obj) && obj[0] === +obj[0]) return Math.max.apply(Math, obj);
|
228
229
|
if (!iterator && _.isEmpty(obj)) return -Infinity;
|
229
230
|
var result = {computed : -Infinity};
|
230
231
|
each(obj, function(value, index, list) {
|
@@ -236,7 +237,7 @@
|
|
236
237
|
|
237
238
|
// Return the minimum element (or element-based computation).
|
238
239
|
_.min = function(obj, iterator, context) {
|
239
|
-
if (!iterator && _.isArray(obj)) return Math.min.apply(Math, obj);
|
240
|
+
if (!iterator && _.isArray(obj) && obj[0] === +obj[0]) return Math.min.apply(Math, obj);
|
240
241
|
if (!iterator && _.isEmpty(obj)) return Infinity;
|
241
242
|
var result = {computed : Infinity};
|
242
243
|
each(obj, function(value, index, list) {
|
@@ -250,19 +251,16 @@
|
|
250
251
|
_.shuffle = function(obj) {
|
251
252
|
var shuffled = [], rand;
|
252
253
|
each(obj, function(value, index, list) {
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
rand = Math.floor(Math.random() * (index + 1));
|
257
|
-
shuffled[index] = shuffled[rand];
|
258
|
-
shuffled[rand] = value;
|
259
|
-
}
|
254
|
+
rand = Math.floor(Math.random() * (index + 1));
|
255
|
+
shuffled[index] = shuffled[rand];
|
256
|
+
shuffled[rand] = value;
|
260
257
|
});
|
261
258
|
return shuffled;
|
262
259
|
};
|
263
260
|
|
264
261
|
// Sort the object's values by a criterion produced by an iterator.
|
265
|
-
_.sortBy = function(obj,
|
262
|
+
_.sortBy = function(obj, val, context) {
|
263
|
+
var iterator = _.isFunction(val) ? val : function(obj) { return obj[val]; };
|
266
264
|
return _.pluck(_.map(obj, function(value, index, list) {
|
267
265
|
return {
|
268
266
|
value : value,
|
@@ -270,6 +268,8 @@
|
|
270
268
|
};
|
271
269
|
}).sort(function(left, right) {
|
272
270
|
var a = left.criteria, b = right.criteria;
|
271
|
+
if (a === void 0) return 1;
|
272
|
+
if (b === void 0) return -1;
|
273
273
|
return a < b ? -1 : a > b ? 1 : 0;
|
274
274
|
}), 'value');
|
275
275
|
};
|
@@ -299,26 +299,26 @@
|
|
299
299
|
};
|
300
300
|
|
301
301
|
// Safely convert anything iterable into a real, live array.
|
302
|
-
_.toArray = function(
|
303
|
-
if (!
|
304
|
-
if (
|
305
|
-
if (_.
|
306
|
-
if (_.
|
307
|
-
return _.values(
|
302
|
+
_.toArray = function(obj) {
|
303
|
+
if (!obj) return [];
|
304
|
+
if (_.isArray(obj)) return slice.call(obj);
|
305
|
+
if (_.isArguments(obj)) return slice.call(obj);
|
306
|
+
if (obj.toArray && _.isFunction(obj.toArray)) return obj.toArray();
|
307
|
+
return _.values(obj);
|
308
308
|
};
|
309
309
|
|
310
310
|
// Return the number of elements in an object.
|
311
311
|
_.size = function(obj) {
|
312
|
-
return _.
|
312
|
+
return _.isArray(obj) ? obj.length : _.keys(obj).length;
|
313
313
|
};
|
314
314
|
|
315
315
|
// Array Functions
|
316
316
|
// ---------------
|
317
317
|
|
318
318
|
// Get the first element of an array. Passing **n** will return the first N
|
319
|
-
// values in the array. Aliased as `head`. The **guard** check
|
320
|
-
// with `_.map`.
|
321
|
-
_.first = _.head = function(array, n, guard) {
|
319
|
+
// values in the array. Aliased as `head` and `take`. The **guard** check
|
320
|
+
// allows it to work with `_.map`.
|
321
|
+
_.first = _.head = _.take = function(array, n, guard) {
|
322
322
|
return (n != null) && !guard ? slice.call(array, 0, n) : array[0];
|
323
323
|
};
|
324
324
|
|
@@ -372,15 +372,17 @@
|
|
372
372
|
// Aliased as `unique`.
|
373
373
|
_.uniq = _.unique = function(array, isSorted, iterator) {
|
374
374
|
var initial = iterator ? _.map(array, iterator) : array;
|
375
|
-
var
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
375
|
+
var results = [];
|
376
|
+
// The `isSorted` flag is irrelevant if the array only contains two elements.
|
377
|
+
if (array.length < 3) isSorted = true;
|
378
|
+
_.reduce(initial, function (memo, value, index) {
|
379
|
+
if (isSorted ? _.last(memo) !== value || !memo.length : !_.include(memo, value)) {
|
380
|
+
memo.push(value);
|
381
|
+
results.push(array[index]);
|
380
382
|
}
|
381
383
|
return memo;
|
382
384
|
}, []);
|
383
|
-
return
|
385
|
+
return results;
|
384
386
|
};
|
385
387
|
|
386
388
|
// Produce an array that contains the union: each distinct element from all of
|
@@ -403,7 +405,7 @@
|
|
403
405
|
// Take the difference between one array and a number of other arrays.
|
404
406
|
// Only the elements present in just the first array will remain.
|
405
407
|
_.difference = function(array) {
|
406
|
-
var rest = _.flatten(slice.call(arguments, 1));
|
408
|
+
var rest = _.flatten(slice.call(arguments, 1), true);
|
407
409
|
return _.filter(array, function(value){ return !_.include(rest, value); });
|
408
410
|
};
|
409
411
|
|
@@ -514,7 +516,7 @@
|
|
514
516
|
// it with the arguments supplied.
|
515
517
|
_.delay = function(func, wait) {
|
516
518
|
var args = slice.call(arguments, 2);
|
517
|
-
return setTimeout(function(){ return func.apply(
|
519
|
+
return setTimeout(function(){ return func.apply(null, args); }, wait);
|
518
520
|
};
|
519
521
|
|
520
522
|
// Defers a function, scheduling it to run after the current call stack has
|
@@ -526,7 +528,7 @@
|
|
526
528
|
// Returns a function, that, when invoked, will only be triggered at most once
|
527
529
|
// during a given window of time.
|
528
530
|
_.throttle = function(func, wait) {
|
529
|
-
var context, args, timeout, throttling, more;
|
531
|
+
var context, args, timeout, throttling, more, result;
|
530
532
|
var whenDone = _.debounce(function(){ more = throttling = false; }, wait);
|
531
533
|
return function() {
|
532
534
|
context = this; args = arguments;
|
@@ -539,24 +541,27 @@
|
|
539
541
|
if (throttling) {
|
540
542
|
more = true;
|
541
543
|
} else {
|
542
|
-
func.apply(context, args);
|
544
|
+
result = func.apply(context, args);
|
543
545
|
}
|
544
546
|
whenDone();
|
545
547
|
throttling = true;
|
548
|
+
return result;
|
546
549
|
};
|
547
550
|
};
|
548
551
|
|
549
552
|
// Returns a function, that, as long as it continues to be invoked, will not
|
550
553
|
// be triggered. The function will be called after it stops being called for
|
551
|
-
// N milliseconds.
|
552
|
-
|
554
|
+
// N milliseconds. If `immediate` is passed, trigger the function on the
|
555
|
+
// leading edge, instead of the trailing.
|
556
|
+
_.debounce = function(func, wait, immediate) {
|
553
557
|
var timeout;
|
554
558
|
return function() {
|
555
559
|
var context = this, args = arguments;
|
556
560
|
var later = function() {
|
557
561
|
timeout = null;
|
558
|
-
func.apply(context, args);
|
562
|
+
if (!immediate) func.apply(context, args);
|
559
563
|
};
|
564
|
+
if (immediate && !timeout) func.apply(context, args);
|
560
565
|
clearTimeout(timeout);
|
561
566
|
timeout = setTimeout(later, wait);
|
562
567
|
};
|
@@ -641,6 +646,15 @@
|
|
641
646
|
return obj;
|
642
647
|
};
|
643
648
|
|
649
|
+
// Return a copy of the object only containing the whitelisted properties.
|
650
|
+
_.pick = function(obj) {
|
651
|
+
var result = {};
|
652
|
+
each(_.flatten(slice.call(arguments, 1)), function(key) {
|
653
|
+
if (key in obj) result[key] = obj[key];
|
654
|
+
});
|
655
|
+
return result;
|
656
|
+
};
|
657
|
+
|
644
658
|
// Fill in a given object with default properties.
|
645
659
|
_.defaults = function(obj) {
|
646
660
|
each(slice.call(arguments, 1), function(source) {
|
@@ -761,6 +775,7 @@
|
|
761
775
|
// Is a given array, string, or object empty?
|
762
776
|
// An "empty" object has no enumerable own-properties.
|
763
777
|
_.isEmpty = function(obj) {
|
778
|
+
if (obj == null) return true;
|
764
779
|
if (_.isArray(obj) || _.isString(obj)) return obj.length === 0;
|
765
780
|
for (var key in obj) if (_.has(obj, key)) return false;
|
766
781
|
return true;
|
@@ -807,6 +822,11 @@
|
|
807
822
|
return toString.call(obj) == '[object Number]';
|
808
823
|
};
|
809
824
|
|
825
|
+
// Is a given object a finite number?
|
826
|
+
_.isFinite = function(obj) {
|
827
|
+
return _.isNumber(obj) && isFinite(obj);
|
828
|
+
};
|
829
|
+
|
810
830
|
// Is the given value `NaN`?
|
811
831
|
_.isNaN = function(obj) {
|
812
832
|
// `NaN` is the only value for which `===` is not reflexive.
|
@@ -868,6 +888,14 @@
|
|
868
888
|
return (''+string).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, ''').replace(/\//g,'/');
|
869
889
|
};
|
870
890
|
|
891
|
+
// If the value of the named property is a function then invoke it;
|
892
|
+
// otherwise, return it.
|
893
|
+
_.result = function(object, property) {
|
894
|
+
if (object == null) return null;
|
895
|
+
var value = object[property];
|
896
|
+
return _.isFunction(value) ? value.call(object) : value;
|
897
|
+
};
|
898
|
+
|
871
899
|
// Add your own custom functions to the Underscore object, ensuring that
|
872
900
|
// they're correctly added to the OOP wrapper as well.
|
873
901
|
_.mixin = function(obj) {
|
@@ -897,39 +925,72 @@
|
|
897
925
|
// guaranteed not to match.
|
898
926
|
var noMatch = /.^/;
|
899
927
|
|
928
|
+
// Certain characters need to be escaped so that they can be put into a
|
929
|
+
// string literal.
|
930
|
+
var escapes = {
|
931
|
+
'\\': '\\',
|
932
|
+
"'": "'",
|
933
|
+
'r': '\r',
|
934
|
+
'n': '\n',
|
935
|
+
't': '\t',
|
936
|
+
'u2028': '\u2028',
|
937
|
+
'u2029': '\u2029'
|
938
|
+
};
|
939
|
+
|
940
|
+
for (var p in escapes) escapes[escapes[p]] = p;
|
941
|
+
var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g;
|
942
|
+
var unescaper = /\\(\\|'|r|n|t|u2028|u2029)/g;
|
943
|
+
|
900
944
|
// Within an interpolation, evaluation, or escaping, remove HTML escaping
|
901
945
|
// that had been previously added.
|
902
946
|
var unescape = function(code) {
|
903
|
-
return code.replace(
|
947
|
+
return code.replace(unescaper, function(match, escape) {
|
948
|
+
return escapes[escape];
|
949
|
+
});
|
904
950
|
};
|
905
951
|
|
906
952
|
// JavaScript micro-templating, similar to John Resig's implementation.
|
907
953
|
// Underscore templating handles arbitrary delimiters, preserves whitespace,
|
908
954
|
// and correctly escapes quotes within interpolated code.
|
909
|
-
_.template = function(
|
910
|
-
|
911
|
-
|
912
|
-
|
913
|
-
|
914
|
-
|
915
|
-
|
916
|
-
|
917
|
-
|
918
|
-
|
919
|
-
|
920
|
-
|
921
|
-
|
922
|
-
|
923
|
-
|
924
|
-
|
925
|
-
|
926
|
-
|
927
|
-
|
928
|
-
|
929
|
-
|
930
|
-
|
931
|
-
|
955
|
+
_.template = function(text, data, settings) {
|
956
|
+
settings = _.extend(_.templateSettings, settings);
|
957
|
+
|
958
|
+
// Compile the template source, taking care to escape characters that
|
959
|
+
// cannot be included in a string literal and then unescape them in code
|
960
|
+
// blocks.
|
961
|
+
var source = "__p+='" + text
|
962
|
+
.replace(escaper, function(match) {
|
963
|
+
return '\\' + escapes[match];
|
964
|
+
})
|
965
|
+
.replace(settings.escape || noMatch, function(match, code) {
|
966
|
+
return "'+\n_.escape(" + unescape(code) + ")+\n'";
|
967
|
+
})
|
968
|
+
.replace(settings.interpolate || noMatch, function(match, code) {
|
969
|
+
return "'+\n(" + unescape(code) + ")+\n'";
|
970
|
+
})
|
971
|
+
.replace(settings.evaluate || noMatch, function(match, code) {
|
972
|
+
return "';\n" + unescape(code) + "\n;__p+='";
|
973
|
+
}) + "';\n";
|
974
|
+
|
975
|
+
// If a variable is not specified, place data values in local scope.
|
976
|
+
if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
|
977
|
+
|
978
|
+
source = "var __p='';" +
|
979
|
+
"var print=function(){__p+=Array.prototype.join.call(arguments, '')};\n" +
|
980
|
+
source + "return __p;\n";
|
981
|
+
|
982
|
+
var render = new Function(settings.variable || 'obj', '_', source);
|
983
|
+
if (data) return render(data, _);
|
984
|
+
var template = function(data) {
|
985
|
+
return render.call(this, data, _);
|
932
986
|
};
|
987
|
+
|
988
|
+
// Provide the compiled function source as a convenience for build time
|
989
|
+
// precompilation.
|
990
|
+
template.source = 'function(' + (settings.variable || 'obj') + '){\n' +
|
991
|
+
source + '}';
|
992
|
+
|
993
|
+
return template;
|
933
994
|
};
|
934
995
|
|
935
996
|
// Add a "chain" function, which will delegate to the wrapper.
|
data/lib/judge.rb
CHANGED
@@ -0,0 +1,21 @@
|
|
1
|
+
module Judge
|
2
|
+
module EachValidator
|
3
|
+
|
4
|
+
def self.included(base)
|
5
|
+
base.send(:extend, ClassMethods)
|
6
|
+
end
|
7
|
+
|
8
|
+
module ClassMethods
|
9
|
+
|
10
|
+
def declare_messages(*keys)
|
11
|
+
send :define_method, :messages_to_lookup do
|
12
|
+
keys
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
::ActiveModel::EachValidator.send(:include, Judge::EachValidator) if defined?(::ActiveModel::EachValidator)
|
@@ -1,95 +1,86 @@
|
|
1
|
+
require 'message_config'
|
2
|
+
|
1
3
|
module Judge
|
2
4
|
|
3
5
|
class MessageCollection
|
4
6
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
:options => {
|
11
|
-
:minimum => :too_short,
|
12
|
-
:maximum => :too_long,
|
13
|
-
:is => :wrong_length
|
14
|
-
}
|
15
|
-
},
|
16
|
-
:format => { :base => :invalid },
|
17
|
-
:inclusion => { :base => :inclusion },
|
18
|
-
:exclusion => { :base => :exclusion },
|
19
|
-
:numericality => { :base => :not_a_number,
|
20
|
-
:options => {
|
21
|
-
:greater_than => :greater_than,
|
22
|
-
:greater_than_or_equal_to => :greater_than_or_equal_to,
|
23
|
-
:equal_to => :equal_to,
|
24
|
-
:less_than => :less_than,
|
25
|
-
:less_than_or_equal_to => :less_than_or_equal_to,
|
26
|
-
:odd => :odd,
|
27
|
-
:even => :even
|
28
|
-
}
|
29
|
-
}
|
30
|
-
}
|
31
|
-
|
32
|
-
ALLOW_BLANK = [:format, :exclusion, :inclusion, :length]
|
33
|
-
|
34
|
-
DEFAULT_OPTS = { :generate => true }
|
35
|
-
|
36
|
-
attr_reader :object, :method, :kind, :options, :mm
|
37
|
-
attr_accessor :messages
|
38
|
-
|
39
|
-
def initialize(object, method, amv, opts = {})
|
40
|
-
opts = DEFAULT_OPTS.merge(opts)
|
7
|
+
include MessageConfig
|
8
|
+
|
9
|
+
attr_reader :object, :method, :amv, :kind, :options
|
10
|
+
|
11
|
+
def initialize(object, method, amv)
|
41
12
|
@object = object
|
42
13
|
@method = method
|
14
|
+
@amv = amv
|
43
15
|
@kind = amv.kind
|
44
16
|
@options = amv.options.dup
|
45
|
-
@mm = MESSAGE_MAP
|
46
17
|
@messages = {}
|
47
|
-
generate_messages!
|
18
|
+
generate_messages!
|
48
19
|
end
|
49
20
|
|
50
21
|
def generate_messages!
|
51
|
-
|
52
|
-
|
53
|
-
self.send(:"generate_#{type}!")
|
54
|
-
end
|
22
|
+
%w{base options integer custom blank}.each do |type|
|
23
|
+
@messages = @messages.merge(self.send(:"#{type}_messages"))
|
55
24
|
end
|
56
25
|
end
|
57
26
|
|
58
27
|
def to_hash
|
59
|
-
messages
|
28
|
+
@messages
|
29
|
+
end
|
30
|
+
|
31
|
+
def custom_messages?
|
32
|
+
amv.respond_to?(:messages_to_lookup) && amv.messages_to_lookup.present?
|
60
33
|
end
|
61
34
|
|
62
35
|
private
|
63
36
|
|
64
|
-
def
|
65
|
-
|
66
|
-
|
67
|
-
|
37
|
+
def base_messages
|
38
|
+
msgs = {}
|
39
|
+
if MESSAGE_MAP.has_key?(kind) && MESSAGE_MAP[kind][:base].present?
|
40
|
+
base_message = MESSAGE_MAP[kind][:base]
|
41
|
+
msgs[base_message] = object.errors.generate_message(method, base_message, options)
|
68
42
|
end
|
43
|
+
msgs
|
69
44
|
end
|
70
45
|
|
71
|
-
def
|
72
|
-
|
73
|
-
|
46
|
+
def options_messages
|
47
|
+
msgs = {}
|
48
|
+
if MESSAGE_MAP.has_key?(kind) && MESSAGE_MAP[kind][:options].present?
|
49
|
+
opt_messages = MESSAGE_MAP[kind][:options]
|
74
50
|
opt_messages.each do |opt, opt_message|
|
75
51
|
if options.has_key?(opt)
|
76
52
|
options_for_interpolation = { :count => options[opt] }.merge(options)
|
77
|
-
|
53
|
+
msgs[opt_message] = object.errors.generate_message(method, opt_message, options_for_interpolation)
|
78
54
|
end
|
79
55
|
end
|
80
56
|
end
|
57
|
+
msgs
|
81
58
|
end
|
82
59
|
|
83
|
-
def
|
84
|
-
|
85
|
-
|
60
|
+
def blank_messages
|
61
|
+
msgs = {}
|
62
|
+
if ALLOW_BLANK.include?(kind) && options[:allow_blank].blank? && @messages[:blank].blank?
|
63
|
+
msgs[:blank] = object.errors.generate_message(method, :blank)
|
86
64
|
end
|
65
|
+
msgs
|
87
66
|
end
|
88
67
|
|
89
|
-
def
|
68
|
+
def integer_messages
|
69
|
+
msgs = {}
|
90
70
|
if kind == :numericality && options[:only_integer].present?
|
91
|
-
|
71
|
+
msgs[:not_an_integer] = object.errors.generate_message(method, :not_an_integer)
|
72
|
+
end
|
73
|
+
msgs
|
74
|
+
end
|
75
|
+
|
76
|
+
def custom_messages
|
77
|
+
msgs = {}
|
78
|
+
if custom_messages?
|
79
|
+
amv.messages_to_lookup.each do |key|
|
80
|
+
msgs[key.to_sym] = object.errors.generate_message(method, key)
|
81
|
+
end
|
92
82
|
end
|
83
|
+
msgs
|
93
84
|
end
|
94
85
|
|
95
86
|
end
|