validates_timeliness 1.1.2 → 1.1.3
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
CHANGED
data/Rakefile
CHANGED
@@ -14,24 +14,10 @@ module ValidatesTimeliness
|
|
14
14
|
# will not be in the attribute cache on first read so will be considered in default
|
15
15
|
# timezone and converted to local time. It is then stored back in the attributes
|
16
16
|
# hash and cached to avoid the need for any subsequent differentiation.
|
17
|
-
#
|
18
|
-
# The wholesale replacement of the Rails time type casting is not done to
|
19
|
-
# preserve the quickest conversion for timestamp columns and also any value
|
20
|
-
# which is never changed during the life of the record object.
|
21
17
|
module AttributeMethods
|
22
18
|
|
23
19
|
def self.included(base)
|
24
20
|
base.extend ClassMethods
|
25
|
-
|
26
|
-
if Rails::VERSION::STRING < '2.1'
|
27
|
-
base.class_eval do
|
28
|
-
class << self
|
29
|
-
def create_time_zone_conversion_attribute?(name, column)
|
30
|
-
false
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
21
|
end
|
36
22
|
|
37
23
|
# Adds check for cached date/time attributes which have been type cast already
|
@@ -57,25 +43,19 @@ module ValidatesTimeliness
|
|
57
43
|
end
|
58
44
|
end
|
59
45
|
|
60
|
-
# Writes attribute value by storing raw value in attributes hash,
|
61
|
-
# then convert it with parser and cache it.
|
62
|
-
#
|
63
46
|
# If Rails dirty attributes is enabled then the value is added to
|
64
47
|
# changed attributes if changed. Can't use the default dirty checking
|
65
48
|
# implementation as it chains the write_attribute method which deletes
|
66
49
|
# the attribute from the cache.
|
67
|
-
def write_date_time_attribute(attr_name, value)
|
68
|
-
column = column_for_attribute(attr_name)
|
50
|
+
def write_date_time_attribute(attr_name, value, type, time_zone_aware)
|
69
51
|
old = read_attribute(attr_name) if defined?(::ActiveRecord::Dirty)
|
70
|
-
new = self.class.parse_date_time(value,
|
52
|
+
new = self.class.parse_date_time(value, type)
|
71
53
|
|
72
|
-
unless
|
54
|
+
unless type == :date || new.nil?
|
73
55
|
new = new.to_time rescue new
|
74
56
|
end
|
75
57
|
|
76
|
-
|
77
|
-
new = new.in_time_zone rescue nil
|
78
|
-
end
|
58
|
+
new = new.in_time_zone if new && time_zone_aware
|
79
59
|
@attributes_cache[attr_name] = new
|
80
60
|
|
81
61
|
if defined?(::ActiveRecord::Dirty) && !changed_attributes.include?(attr_name) && old != new
|
@@ -84,6 +64,24 @@ module ValidatesTimeliness
|
|
84
64
|
@attributes[attr_name] = value
|
85
65
|
end
|
86
66
|
|
67
|
+
# If reloading then check if cached, which means its in local time.
|
68
|
+
# If local, convert with parser as local timezone, otherwise use
|
69
|
+
# read_attribute method for quick default type cast of values from
|
70
|
+
# database using default timezone.
|
71
|
+
def read_date_time_attribute(attr_name, type, time_zone_aware, reload = false)
|
72
|
+
cached = @attributes_cache[attr_name]
|
73
|
+
return cached if @attributes_cache.has_key?(attr_name) && !reload
|
74
|
+
|
75
|
+
if @attributes_cache.has_key?(attr_name)
|
76
|
+
time = read_attribute_before_type_cast(attr_name)
|
77
|
+
time = self.class.parse_date_time(date, type)
|
78
|
+
else
|
79
|
+
time = read_attribute(attr_name)
|
80
|
+
@attributes[attr_name] = time && time_zone_aware ? time.in_time_zone : time
|
81
|
+
end
|
82
|
+
@attributes_cache[attr_name] = time && time_zone_aware ? time.in_time_zone : time
|
83
|
+
end
|
84
|
+
|
87
85
|
module ClassMethods
|
88
86
|
|
89
87
|
# Override AR method to define attribute reader and writer method for
|
@@ -94,8 +92,9 @@ module ValidatesTimeliness
|
|
94
92
|
unless instance_method_already_implemented?(name)
|
95
93
|
if self.serialized_attributes[name]
|
96
94
|
define_read_method_for_serialized_attribute(name)
|
97
|
-
elsif
|
98
|
-
|
95
|
+
elsif [:date, :time, :datetime].include?(column.type)
|
96
|
+
time_zone_aware = create_time_zone_conversion_attribute?(name, column) rescue false
|
97
|
+
define_read_method_for_dates_and_times(name, column.type, time_zone_aware)
|
99
98
|
else
|
100
99
|
define_read_method(name.to_sym, name, column)
|
101
100
|
end
|
@@ -103,7 +102,8 @@ module ValidatesTimeliness
|
|
103
102
|
|
104
103
|
unless instance_method_already_implemented?("#{name}=")
|
105
104
|
if [:date, :time, :datetime].include?(column.type)
|
106
|
-
|
105
|
+
time_zone_aware = create_time_zone_conversion_attribute?(name, column) rescue false
|
106
|
+
define_write_method_for_dates_and_times(name, column.type, time_zone_aware)
|
107
107
|
else
|
108
108
|
define_write_method(name.to_sym)
|
109
109
|
end
|
@@ -116,32 +116,19 @@ module ValidatesTimeliness
|
|
116
116
|
end
|
117
117
|
|
118
118
|
# Define write method for date, time and datetime columns
|
119
|
-
def define_write_method_for_dates_and_times(attr_name)
|
119
|
+
def define_write_method_for_dates_and_times(attr_name, type, time_zone_aware)
|
120
120
|
method_body = <<-EOV
|
121
121
|
def #{attr_name}=(value)
|
122
|
-
write_date_time_attribute('#{attr_name}', value)
|
122
|
+
write_date_time_attribute('#{attr_name}', value, #{type.inspect}, #{time_zone_aware})
|
123
123
|
end
|
124
124
|
EOV
|
125
125
|
evaluate_attribute_method attr_name, method_body, "#{attr_name}="
|
126
126
|
end
|
127
127
|
|
128
|
-
|
129
|
-
# which means its in local time. If local, convert with parser as local
|
130
|
-
# timezone, otherwise use read_attribute method for quick default type
|
131
|
-
# cast of values from database using default timezone.
|
132
|
-
def define_read_method_for_time_zone_conversion(attr_name)
|
128
|
+
def define_read_method_for_dates_and_times(attr_name, type, time_zone_aware)
|
133
129
|
method_body = <<-EOV
|
134
130
|
def #{attr_name}(reload = false)
|
135
|
-
|
136
|
-
return cached if @attributes_cache.has_key?('#{attr_name}') && !reload
|
137
|
-
if @attributes_cache.has_key?('#{attr_name}')
|
138
|
-
time = read_attribute_before_type_cast('#{attr_name}')
|
139
|
-
time = self.class.parse_date_time(date, :datetime)
|
140
|
-
else
|
141
|
-
time = read_attribute('#{attr_name}')
|
142
|
-
@attributes['#{attr_name}'] = time.in_time_zone rescue nil
|
143
|
-
end
|
144
|
-
@attributes_cache['#{attr_name}'] = time.in_time_zone rescue nil
|
131
|
+
read_date_time_attribute('#{attr_name}', #{type.inspect}, #{time_zone_aware}, reload)
|
145
132
|
end
|
146
133
|
EOV
|
147
134
|
evaluate_attribute_method attr_name, method_body
|
@@ -161,18 +161,18 @@ module ValidatesTimeliness
|
|
161
161
|
# Returns 7 part time array.
|
162
162
|
def parse(string, type, strict=true)
|
163
163
|
return string unless string.is_a?(String)
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
break
|
164
|
+
|
165
|
+
matches = nil
|
166
|
+
exp, processor = expression_set(type, string).find do |regexp, proc|
|
167
|
+
full = /\A#{regexp}\Z/ if strict
|
168
|
+
full ||= case type
|
169
|
+
when :datetime then /\A#{regexp}\Z/
|
170
|
+
when :date then /\A#{regexp}/
|
171
|
+
else /#{regexp}\Z/
|
173
172
|
end
|
173
|
+
matches = full.match(string.strip)
|
174
174
|
end
|
175
|
-
|
175
|
+
processor.call(*matches[1..7]) if matches
|
176
176
|
end
|
177
177
|
|
178
178
|
# Delete formats of specified type. Error raised if format not found.
|
@@ -299,22 +299,6 @@ module ValidatesTimeliness
|
|
299
299
|
return month.to_i if month.to_i.nonzero?
|
300
300
|
Date::ABBR_MONTHNAMES.index(month.capitalize) || Date::MONTHNAMES.index(month.capitalize)
|
301
301
|
end
|
302
|
-
|
303
|
-
def month_names
|
304
|
-
@@month_names = if defined?(I18n)
|
305
|
-
I18n('dates.months')
|
306
|
-
else
|
307
|
-
Date::MONTHNAMES
|
308
|
-
end
|
309
|
-
end
|
310
|
-
|
311
|
-
def abbreviated_month_names
|
312
|
-
@@abbreviated_month_names = if defined?(I18n)
|
313
|
-
I18n('dates.months')
|
314
|
-
else
|
315
|
-
Date::ABBR_MONTHNAMES
|
316
|
-
end
|
317
|
-
end
|
318
302
|
|
319
303
|
def microseconds(usec)
|
320
304
|
(".#{usec}".to_f * 1_000_000).to_i
|
@@ -23,6 +23,24 @@ describe ValidatesTimeliness::ActiveRecord::AttributeMethods do
|
|
23
23
|
@person.birth_date_and_time = "2000-01-01 12:00"
|
24
24
|
end
|
25
25
|
|
26
|
+
it "should call read_date_time_attribute when date attribute is retrieved" do
|
27
|
+
@person.should_receive(:read_date_time_attribute)
|
28
|
+
@person.birth_date = "2000-01-01"
|
29
|
+
@person.birth_date
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should call read_date_time_attribute when time attribute is retrieved" do
|
33
|
+
@person.should_receive(:read_date_time_attribute)
|
34
|
+
@person.birth_time = "12:00"
|
35
|
+
@person.birth_time
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should call rea_date_time_attribute when datetime attribute is retrieved" do
|
39
|
+
@person.should_receive(:read_date_time_attribute)
|
40
|
+
@person.birth_date_and_time = "2000-01-01 12:00"
|
41
|
+
@person.birth_date_and_time
|
42
|
+
end
|
43
|
+
|
26
44
|
it "should call parser on write for datetime attribute" do
|
27
45
|
@person.class.should_receive(:parse_date_time).once
|
28
46
|
@person.birth_date_and_time = "2000-01-01 02:03:04"
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: validates_timeliness
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Adam Meehan
|
@@ -9,7 +9,7 @@ autorequire: validates_timeliness
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-01-
|
12
|
+
date: 2009-01-13 00:00:00 +11:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|