markos_validates_timeliness 2.3.2
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/CHANGELOG +121 -0
- data/LICENSE +20 -0
- data/README.rdoc +402 -0
- data/Rakefile +52 -0
- data/TODO +8 -0
- data/lib/validates_timeliness/action_view/instance_tag.rb +52 -0
- data/lib/validates_timeliness/active_record/attribute_methods.rb +77 -0
- data/lib/validates_timeliness/active_record/multiparameter_attributes.rb +69 -0
- data/lib/validates_timeliness/formats.rb +368 -0
- data/lib/validates_timeliness/locale/en.new.yml +18 -0
- data/lib/validates_timeliness/locale/en.old.yml +18 -0
- data/lib/validates_timeliness/matcher.rb +1 -0
- data/lib/validates_timeliness/parser.rb +44 -0
- data/lib/validates_timeliness/spec/rails/matchers/validate_timeliness.rb +162 -0
- data/lib/validates_timeliness/validation_methods.rb +46 -0
- data/lib/validates_timeliness/validator.rb +230 -0
- data/lib/validates_timeliness/version.rb +3 -0
- data/lib/validates_timeliness.rb +59 -0
- data/spec/action_view/instance_tag_spec.rb +194 -0
- data/spec/active_record/attribute_methods_spec.rb +157 -0
- data/spec/active_record/multiparameter_attributes_spec.rb +118 -0
- data/spec/formats_spec.rb +313 -0
- data/spec/ginger_scenarios.rb +19 -0
- data/spec/parser_spec.rb +65 -0
- data/spec/resources/application.rb +2 -0
- data/spec/resources/person.rb +3 -0
- data/spec/resources/schema.rb +10 -0
- data/spec/resources/sqlite_patch.rb +19 -0
- data/spec/spec/rails/matchers/validate_timeliness_spec.rb +245 -0
- data/spec/spec_helper.rb +58 -0
- data/spec/time_travel/MIT-LICENSE +20 -0
- data/spec/time_travel/time_extensions.rb +33 -0
- data/spec/time_travel/time_travel.rb +12 -0
- data/spec/validator_spec.rb +723 -0
- metadata +104 -0
@@ -0,0 +1,162 @@
|
|
1
|
+
module Spec
|
2
|
+
module Rails
|
3
|
+
module Matchers
|
4
|
+
class ValidateTimeliness
|
5
|
+
|
6
|
+
VALIDITY_TEST_VALUES = {
|
7
|
+
:date => {:pass => '2000-01-01', :fail => '2000-01-32'},
|
8
|
+
:time => {:pass => '12:00', :fail => '25:00'},
|
9
|
+
:datetime => {:pass => '2000-01-01 00:00:00', :fail => '2000-01-32 00:00:00'}
|
10
|
+
}
|
11
|
+
|
12
|
+
OPTION_TEST_SETTINGS = {
|
13
|
+
:is_at => { :method => :+, :modify_on => :invalid },
|
14
|
+
:before => { :method => :-, :modify_on => :valid },
|
15
|
+
:after => { :method => :+, :modify_on => :valid },
|
16
|
+
:on_or_before => { :method => :+, :modify_on => :invalid },
|
17
|
+
:on_or_after => { :method => :-, :modify_on => :invalid }
|
18
|
+
}
|
19
|
+
|
20
|
+
def initialize(attribute, options)
|
21
|
+
@expected, @options = attribute, options
|
22
|
+
@validator = ValidatesTimeliness::Validator.new(options)
|
23
|
+
end
|
24
|
+
|
25
|
+
def matches?(record)
|
26
|
+
@record = record
|
27
|
+
@type = @options[:type]
|
28
|
+
|
29
|
+
valid = test_validity
|
30
|
+
|
31
|
+
valid = test_option(:is_at) if valid && @options[:is_at]
|
32
|
+
valid = test_option(:before) if valid && @options[:before]
|
33
|
+
valid = test_option(:after) if valid && @options[:after]
|
34
|
+
valid = test_option(:on_or_before) if valid && @options[:on_or_before]
|
35
|
+
valid = test_option(:on_or_after) if valid && @options[:on_or_after]
|
36
|
+
valid = test_between if valid && @options[:between]
|
37
|
+
|
38
|
+
return valid
|
39
|
+
end
|
40
|
+
|
41
|
+
def failure_message
|
42
|
+
"expected model to validate #{@type} attribute #{@expected.inspect} with #{@last_failure}"
|
43
|
+
end
|
44
|
+
|
45
|
+
def negative_failure_message
|
46
|
+
"expected not to validate #{@type} attribute #{@expected.inspect}"
|
47
|
+
end
|
48
|
+
|
49
|
+
def description
|
50
|
+
"have validated #{@type} attribute #{@expected.inspect}"
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def test_validity
|
56
|
+
invalid_value = VALIDITY_TEST_VALUES[@type][:fail]
|
57
|
+
valid_value = parse_and_cast(VALIDITY_TEST_VALUES[@type][:pass])
|
58
|
+
error_matching(invalid_value, "invalid_#{@type}".to_sym) &&
|
59
|
+
no_error_matching(valid_value, "invalid_#{@type}".to_sym)
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_option(option)
|
63
|
+
settings = OPTION_TEST_SETTINGS[option]
|
64
|
+
boundary = parse_and_cast(@options[option])
|
65
|
+
|
66
|
+
method = settings[:method]
|
67
|
+
|
68
|
+
valid_value, invalid_value = if settings[:modify_on] == :valid
|
69
|
+
[ boundary.send(method, 1), boundary ]
|
70
|
+
else
|
71
|
+
[ boundary, boundary.send(method, 1) ]
|
72
|
+
end
|
73
|
+
|
74
|
+
error_matching(invalid_value, option) &&
|
75
|
+
no_error_matching(valid_value, option)
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_before
|
79
|
+
before = parse_and_cast(@options[:before])
|
80
|
+
|
81
|
+
error_matching(before - 1, :before) &&
|
82
|
+
no_error_matching(before, :before)
|
83
|
+
end
|
84
|
+
|
85
|
+
def test_between
|
86
|
+
between = parse_and_cast(@options[:between])
|
87
|
+
|
88
|
+
error_matching(between.first - 1, :between) &&
|
89
|
+
error_matching(between.last + 1, :between) &&
|
90
|
+
no_error_matching(between.first, :between) &&
|
91
|
+
no_error_matching(between.last, :between)
|
92
|
+
end
|
93
|
+
|
94
|
+
def parse_and_cast(value)
|
95
|
+
value = @validator.class.send(:evaluate_option_value, value, @type, @record)
|
96
|
+
@validator.class.send(:type_cast_value, value, @type)
|
97
|
+
end
|
98
|
+
|
99
|
+
def error_matching(value, option)
|
100
|
+
match = error_message_for(option)
|
101
|
+
@record.send("#{@expected}=", value)
|
102
|
+
@record.valid?
|
103
|
+
errors = @record.errors.on(@expected)
|
104
|
+
pass = [ errors ].flatten.any? {|error| /#{match}/ === error }
|
105
|
+
@last_failure = "error matching '#{match}' when value is #{format_value(value)}" unless pass
|
106
|
+
pass
|
107
|
+
end
|
108
|
+
|
109
|
+
def no_error_matching(value, option)
|
110
|
+
pass = !error_matching(value, option)
|
111
|
+
unless pass
|
112
|
+
error = error_message_for(option)
|
113
|
+
@last_failure = "no error matching '#{error}' when value is #{format_value(value)}"
|
114
|
+
end
|
115
|
+
pass
|
116
|
+
end
|
117
|
+
|
118
|
+
def error_message_for(message)
|
119
|
+
restriction = @validator.class.send(:evaluate_option_value, @validator.configuration[message], @type, @record)
|
120
|
+
|
121
|
+
if restriction
|
122
|
+
restriction = @validator.class.send(:type_cast_value, restriction, @type)
|
123
|
+
interpolate = @validator.send(:interpolation_values, message, restriction)
|
124
|
+
end
|
125
|
+
|
126
|
+
if defined?(I18n)
|
127
|
+
interpolate ||= {}
|
128
|
+
options = interpolate.merge(:default => @validator.send(:custom_error_messages)[message])
|
129
|
+
if defined?(ActiveRecord::Error)
|
130
|
+
ActiveRecord::Error.new(@record, @expected, message, options).message
|
131
|
+
else
|
132
|
+
@record.errors.generate_message(@expected, message, options)
|
133
|
+
end
|
134
|
+
else
|
135
|
+
interpolate ||= nil
|
136
|
+
@validator.error_messages[message] % interpolate
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def format_value(value)
|
141
|
+
return value if value.is_a?(String)
|
142
|
+
value.strftime(@validator.class.error_value_formats[@type])
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def validate_date(attribute, options={})
|
147
|
+
options[:type] = :date
|
148
|
+
ValidateTimeliness.new(attribute, options)
|
149
|
+
end
|
150
|
+
|
151
|
+
def validate_time(attribute, options={})
|
152
|
+
options[:type] = :time
|
153
|
+
ValidateTimeliness.new(attribute, options)
|
154
|
+
end
|
155
|
+
|
156
|
+
def validate_datetime(attribute, options={})
|
157
|
+
options[:type] = :datetime
|
158
|
+
ValidateTimeliness.new(attribute, options)
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module ValidatesTimeliness
|
2
|
+
module ValidationMethods
|
3
|
+
|
4
|
+
def self.included(base)
|
5
|
+
base.extend ClassMethods
|
6
|
+
end
|
7
|
+
|
8
|
+
module ClassMethods
|
9
|
+
|
10
|
+
def validates_time(*attr_names)
|
11
|
+
configuration = attr_names.extract_options!
|
12
|
+
configuration[:type] = :time
|
13
|
+
validates_timeliness_of(attr_names, configuration)
|
14
|
+
end
|
15
|
+
|
16
|
+
def validates_date(*attr_names)
|
17
|
+
configuration = attr_names.extract_options!
|
18
|
+
configuration[:type] = :date
|
19
|
+
validates_timeliness_of(attr_names, configuration)
|
20
|
+
end
|
21
|
+
|
22
|
+
def validates_datetime(*attr_names)
|
23
|
+
configuration = attr_names.extract_options!
|
24
|
+
configuration[:type] = :datetime
|
25
|
+
validates_timeliness_of(attr_names, configuration)
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def validates_timeliness_of(attr_names, configuration)
|
31
|
+
validator = ValidatesTimeliness::Validator.new(configuration.symbolize_keys)
|
32
|
+
|
33
|
+
# bypass handling of allow_nil and allow_blank to validate raw value
|
34
|
+
configuration.delete(:allow_nil)
|
35
|
+
configuration.delete(:allow_blank)
|
36
|
+
validates_each(attr_names, configuration) do |record, attr_name, value|
|
37
|
+
validator.call(record, attr_name, value)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
ActiveRecord::Base.send(:include, ValidatesTimeliness::ValidationMethods)
|
@@ -0,0 +1,230 @@
|
|
1
|
+
#TODO remove deprecated option :equal_to
|
2
|
+
module ValidatesTimeliness
|
3
|
+
|
4
|
+
class Validator
|
5
|
+
cattr_accessor :error_value_formats
|
6
|
+
cattr_accessor :ignore_restriction_errors
|
7
|
+
self.ignore_restriction_errors = false
|
8
|
+
|
9
|
+
RESTRICTION_METHODS = {
|
10
|
+
:is_at => :==,
|
11
|
+
:equal_to => :==,
|
12
|
+
:before => :<,
|
13
|
+
:after => :>,
|
14
|
+
:on_or_before => :<=,
|
15
|
+
:on_or_after => :>=,
|
16
|
+
:between => lambda {|v, r| (r.first..r.last).include?(v) }
|
17
|
+
}
|
18
|
+
|
19
|
+
VALID_OPTION_KEYS = [
|
20
|
+
:on, :if, :unless, :allow_nil, :empty, :allow_blank,
|
21
|
+
:with_time, :with_date, :ignore_usec, :format,
|
22
|
+
:invalid_time_message, :invalid_date_message, :invalid_datetime_message
|
23
|
+
] + RESTRICTION_METHODS.keys.map {|option| [option, "#{option}_message".to_sym] }.flatten
|
24
|
+
|
25
|
+
DEFAULT_OPTIONS = { :on => :save, :type => :datetime, :allow_nil => false, :allow_blank => false, :ignore_usec => false }
|
26
|
+
|
27
|
+
attr_reader :configuration, :type
|
28
|
+
|
29
|
+
def initialize(configuration)
|
30
|
+
@configuration = DEFAULT_OPTIONS.merge(configuration)
|
31
|
+
@type = @configuration.delete(:type)
|
32
|
+
validate_options(@configuration)
|
33
|
+
end
|
34
|
+
|
35
|
+
def call(record, attr_name, value)
|
36
|
+
raw_value = raw_value(record, attr_name) || value
|
37
|
+
|
38
|
+
if value.is_a?(String) || configuration[:format]
|
39
|
+
value = ValidatesTimeliness::Parser.parse(raw_value, type, :strict => false, :format => configuration[:format])
|
40
|
+
end
|
41
|
+
|
42
|
+
return if (raw_value.nil? && configuration[:allow_nil]) || (raw_value.blank? && configuration[:allow_blank])
|
43
|
+
|
44
|
+
return add_error(record, attr_name, :blank) if raw_value.blank?
|
45
|
+
return add_error(record, attr_name, "invalid_#{type}".to_sym) if value.nil?
|
46
|
+
|
47
|
+
validate_restrictions(record, attr_name, value)
|
48
|
+
end
|
49
|
+
|
50
|
+
def error_messages
|
51
|
+
@error_messages ||= ::ActiveRecord::Errors.default_error_messages.merge(custom_error_messages)
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def raw_value(record, attr_name)
|
57
|
+
record.send("#{attr_name}_before_type_cast") rescue nil
|
58
|
+
end
|
59
|
+
|
60
|
+
def validate_restrictions(record, attr_name, value)
|
61
|
+
if configuration[:with_time] || configuration[:with_date]
|
62
|
+
value = combine_date_and_time(value, record)
|
63
|
+
end
|
64
|
+
|
65
|
+
value = self.class.type_cast_value(value, implied_type, configuration[:ignore_usec])
|
66
|
+
|
67
|
+
return if value.nil?
|
68
|
+
|
69
|
+
RESTRICTION_METHODS.each do |option, method|
|
70
|
+
next unless restriction = configuration[option]
|
71
|
+
begin
|
72
|
+
restriction = self.class.evaluate_option_value(restriction, implied_type, record)
|
73
|
+
next if restriction.nil?
|
74
|
+
restriction = self.class.type_cast_value(restriction, implied_type, configuration[:ignore_usec])
|
75
|
+
|
76
|
+
unless evaluate_restriction(restriction, value, method)
|
77
|
+
add_error(record, attr_name, option, interpolation_values(option, restriction))
|
78
|
+
end
|
79
|
+
rescue
|
80
|
+
unless self.class.ignore_restriction_errors
|
81
|
+
add_error(record, attr_name, "restriction '#{option}' value was invalid")
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def interpolation_values(option, restriction)
|
88
|
+
format = self.class.error_value_format_for(type)
|
89
|
+
restriction = [restriction] unless restriction.is_a?(Array)
|
90
|
+
|
91
|
+
if defined?(I18n)
|
92
|
+
interpolations = {}
|
93
|
+
keys = restriction.size == 1 ? [:restriction] : [:earliest, :latest]
|
94
|
+
keys.each_with_index {|key, i| interpolations[key] = restriction[i].strftime(format) }
|
95
|
+
interpolations
|
96
|
+
else
|
97
|
+
restriction.map {|r| r.strftime(format) }
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def evaluate_restriction(restriction, value, comparator)
|
102
|
+
return true if restriction.nil?
|
103
|
+
|
104
|
+
case comparator
|
105
|
+
when Symbol
|
106
|
+
value.send(comparator, restriction)
|
107
|
+
when Proc
|
108
|
+
comparator.call(value, restriction)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def add_error(record, attr_name, message, interpolate=nil)
|
113
|
+
if defined?(I18n)
|
114
|
+
custom = custom_error_messages[message]
|
115
|
+
record.errors.add(attr_name, message, { :default => custom }.merge(interpolate || {}))
|
116
|
+
else
|
117
|
+
message = error_messages[message] if message.is_a?(Symbol)
|
118
|
+
record.errors.add(attr_name, message % interpolate)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def custom_error_messages
|
123
|
+
@custom_error_messages ||= configuration.inject({}) {|msgs, (k, v)|
|
124
|
+
if md = /(.*)_message$/.match(k.to_s)
|
125
|
+
msgs[md[1].to_sym] = v
|
126
|
+
end
|
127
|
+
msgs
|
128
|
+
}
|
129
|
+
end
|
130
|
+
|
131
|
+
def combine_date_and_time(value, record)
|
132
|
+
if type == :date
|
133
|
+
date = value
|
134
|
+
time = configuration[:with_time]
|
135
|
+
else
|
136
|
+
date = configuration[:with_date]
|
137
|
+
time = value
|
138
|
+
end
|
139
|
+
date, time = self.class.evaluate_option_value(date, :date, record), self.class.evaluate_option_value(time, :time, record)
|
140
|
+
return if date.nil? || time.nil?
|
141
|
+
ValidatesTimeliness::Parser.make_time([date.year, date.month, date.day, time.hour, time.min, time.sec, time.usec])
|
142
|
+
end
|
143
|
+
|
144
|
+
def validate_options(options)
|
145
|
+
if options.key?(:equal_to)
|
146
|
+
::ActiveSupport::Deprecation.warn("ValidatesTimeliness :equal_to option is deprecated due to clash with a default Rails option. Use :is_at instead. You will need to fix any I18n error message references to this option date/time attributes now.")
|
147
|
+
options[:is_at] = options.delete(:equal_to)
|
148
|
+
options[:is_at_message] = options.delete(:equal_to_message)
|
149
|
+
end
|
150
|
+
|
151
|
+
invalid_for_type = ([:time, :date, :datetime] - [type]).map {|k| "invalid_#{k}_message".to_sym }
|
152
|
+
invalid_for_type << :with_date unless type == :time
|
153
|
+
invalid_for_type << :with_time unless type == :date
|
154
|
+
options.assert_valid_keys(VALID_OPTION_KEYS - invalid_for_type)
|
155
|
+
end
|
156
|
+
|
157
|
+
def implied_type
|
158
|
+
@implied_type ||= configuration[:with_date] || configuration[:with_time] ? :datetime : type
|
159
|
+
end
|
160
|
+
|
161
|
+
# class methods
|
162
|
+
class << self
|
163
|
+
|
164
|
+
def error_value_format_for(type)
|
165
|
+
if defined?(I18n)
|
166
|
+
# work around for syntax check in vendored I18n for Rails <= 2.3.3
|
167
|
+
I18n.t('validates_timeliness.error_value_formats')[type] || error_value_formats[type]
|
168
|
+
else
|
169
|
+
error_value_formats[type]
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
def evaluate_option_value(value, type, record)
|
174
|
+
case value
|
175
|
+
when Time, Date
|
176
|
+
value
|
177
|
+
when Symbol
|
178
|
+
evaluate_option_value(record.send(value), type, record)
|
179
|
+
when Proc
|
180
|
+
result = value.arity > 0 ? value.call(record) : value.call
|
181
|
+
evaluate_option_value(result, type, record)
|
182
|
+
when Array
|
183
|
+
value.map {|r| evaluate_option_value(r, type, record) }.sort
|
184
|
+
when Range
|
185
|
+
evaluate_option_value([value.first, value.last], type, record)
|
186
|
+
else
|
187
|
+
ValidatesTimeliness::Parser.parse(value, type, :strict => false)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
def type_cast_value(value, type, ignore_usec=false)
|
192
|
+
if value.is_a?(Array)
|
193
|
+
value.map {|v| type_cast_value(v, type, ignore_usec) }
|
194
|
+
else
|
195
|
+
value = case type
|
196
|
+
when :time
|
197
|
+
dummy_time(value)
|
198
|
+
when :date
|
199
|
+
value.to_date
|
200
|
+
when :datetime
|
201
|
+
if value.is_a?(Time) || value.is_a?(DateTime)
|
202
|
+
value.to_time
|
203
|
+
else
|
204
|
+
value.to_time(ValidatesTimeliness.default_timezone)
|
205
|
+
end
|
206
|
+
else
|
207
|
+
nil
|
208
|
+
end
|
209
|
+
if ignore_usec && value.is_a?(Time)
|
210
|
+
ValidatesTimeliness::Parser.make_time(Array(value).reverse[4..9])
|
211
|
+
else
|
212
|
+
value
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
def dummy_time(value)
|
218
|
+
if value.is_a?(Time) || value.is_a?(DateTime)
|
219
|
+
time = [value.hour, value.min, value.sec]
|
220
|
+
else
|
221
|
+
time = [0,0,0]
|
222
|
+
end
|
223
|
+
dummy_date = ValidatesTimeliness::Formats.dummy_date_for_time_type
|
224
|
+
ValidatesTimeliness::Parser.make_time(dummy_date + time)
|
225
|
+
end
|
226
|
+
|
227
|
+
end
|
228
|
+
|
229
|
+
end
|
230
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'validates_timeliness/formats'
|
2
|
+
require 'validates_timeliness/parser'
|
3
|
+
require 'validates_timeliness/validator'
|
4
|
+
require 'validates_timeliness/validation_methods'
|
5
|
+
require 'validates_timeliness/active_record/attribute_methods'
|
6
|
+
require 'validates_timeliness/active_record/multiparameter_attributes'
|
7
|
+
require 'validates_timeliness/action_view/instance_tag'
|
8
|
+
begin
|
9
|
+
i18n_path = $:.grep(/active_support\/vendor\/i18n-/)
|
10
|
+
if i18n_path.empty?
|
11
|
+
require 'i18n/version'
|
12
|
+
else
|
13
|
+
require i18n_path[0] + '/version'
|
14
|
+
end
|
15
|
+
rescue LoadError
|
16
|
+
end if defined?(I18n)
|
17
|
+
|
18
|
+
module ValidatesTimeliness
|
19
|
+
|
20
|
+
mattr_accessor :default_timezone
|
21
|
+
self.default_timezone = :utc
|
22
|
+
|
23
|
+
mattr_accessor :use_time_zones
|
24
|
+
self.use_time_zones = false
|
25
|
+
|
26
|
+
I18N_LATEST = defined?(I18n::VERSION) && I18n::VERSION >= '0.4.0'
|
27
|
+
locale_file = I18N_LATEST ? 'en.new.yml' : 'en.old.yml'
|
28
|
+
LOCALE_PATH = File.expand_path(File.join(File.dirname(__FILE__),'validates_timeliness','locale',locale_file))
|
29
|
+
|
30
|
+
class << self
|
31
|
+
|
32
|
+
def enable_datetime_select_extension!
|
33
|
+
enable_datetime_select_invalid_value_extension!
|
34
|
+
enable_multiparameter_attributes_extension!
|
35
|
+
end
|
36
|
+
|
37
|
+
def load_error_messages
|
38
|
+
defaults = YAML::load(IO.read(LOCALE_PATH))['en']
|
39
|
+
ValidatesTimeliness::Validator.error_value_formats = defaults['validates_timeliness']['error_value_formats'].symbolize_keys
|
40
|
+
|
41
|
+
if defined?(I18n)
|
42
|
+
I18n.load_path.unshift(LOCALE_PATH)
|
43
|
+
I18n.reload!
|
44
|
+
else
|
45
|
+
errors = defaults['activerecord']['errors']['messages'].inject({}) {|h,(k,v)| h[k.to_sym] = v.gsub(/\{\{\w*\}\}/, '%s');h }
|
46
|
+
::ActiveRecord::Errors.default_error_messages.update(errors)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def setup_for_rails
|
51
|
+
self.default_timezone = ::ActiveRecord::Base.default_timezone
|
52
|
+
self.use_time_zones = ::ActiveRecord::Base.time_zone_aware_attributes rescue false
|
53
|
+
self.enable_active_record_datetime_parser!
|
54
|
+
load_error_messages
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
ValidatesTimeliness.setup_for_rails
|