acts_as_dated_detail 0.0.1 → 0.0.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.
@@ -19,6 +19,7 @@ module ActiveRecord
19
19
  )
20
20
  tracked_attribute_writer_methods << %(
21
21
  def #{attribute}=(value)
22
+ write_attribute('#{attribute}', value)
22
23
  dated_detail.send('#{attribute}=', value)
23
24
  end
24
25
  )
@@ -34,6 +35,8 @@ module ActiveRecord
34
35
 
35
36
  include ActiveRecord::Acts::Dated::InstanceMethods
36
37
 
38
+ alias_method_chain :reload, :dated_detail
39
+
37
40
  # def self.columns
38
41
  # tracked_columns_hash = #{acts_as_dated_detail_class.to_s}.columns_hash.slice(*#{acts_as_dated_detail_class.to_s}.tracked_attributes)
39
42
  # @columns ||= tracked_columns_hash.inject(super.columns) do |columns, (key, value)|
@@ -46,12 +49,15 @@ module ActiveRecord
46
49
  end
47
50
 
48
51
  module InstanceMethods
52
+
53
+
49
54
  def on
50
55
  @time ||= Time.now
51
56
  end
52
57
 
53
58
  def on=(time)
54
59
  @time = time
60
+ @fixed_time = true
55
61
  @dated_detail = nil
56
62
  end
57
63
 
@@ -59,10 +65,29 @@ module ActiveRecord
59
65
  @dated_detail ||= dated_details.on(on).first || dated_details.build
60
66
  end
61
67
 
68
+ def current?
69
+ !@fixed_time
70
+ end
71
+
72
+ def current!
73
+ @fixed_time = false
74
+ @dated_detail = nil
75
+ @time = nil
76
+ end
77
+
78
+ def reload_with_dated_detail
79
+ if current?
80
+ @dated_detail = nil
81
+ @time = nil
82
+ end
83
+ reload_without_dated_detail
84
+ end
85
+
62
86
  private
63
87
 
64
88
  def save_dated_detail
65
89
  dated_detail.save!
90
+ @time = dated_detail.start_on
66
91
  end
67
92
  end
68
93
  end
@@ -11,6 +11,7 @@ module ActiveRecord
11
11
  belongs_to :#{self.name.underscore.sub(/_dated_detail$/, '')}
12
12
 
13
13
  before_update :split!
14
+ before_save :set_start_date
14
15
 
15
16
  named_scope :on, lambda { |time| { :conditions => "\#{start_on_or_before_condition(time)} AND \#{end_on_or_after_condition(time)}" } }
16
17
 
@@ -36,9 +37,8 @@ module ActiveRecord
36
37
  end
37
38
 
38
39
  module InstanceMethods
39
- def initialize(*args)
40
- super
41
- self.start_on = Time.now
40
+ def set_start_date
41
+ self.start_on ||= Time.now
42
42
  end
43
43
 
44
44
  def split!
@@ -98,6 +98,7 @@ class ActsAsDatedDetailTest < Test::Unit::TestCase
98
98
  Time.stubs(:now).returns(time)
99
99
  pirate.update_attributes(:name => pirate_name(time), :catchphrase => catchphrase(time), :ruthlessness => ruthlessness(time), :birth_date => time, :parrot => create_parrot(time))
100
100
  end
101
+ # A lot of tests rely on this method stubbing Time.now
101
102
  Time.stubs(:now).returns(now)
102
103
  pirate
103
104
  end
@@ -119,7 +120,7 @@ class ParentTest < ActsAsDatedDetailTest
119
120
  # Creation
120
121
 
121
122
  def test_related_dated_detail_created_along_with_model
122
- pirate = Pirate.create!
123
+ pirate = create_pirate
123
124
  assert_equal 1, pirate.dated_details.count
124
125
  end
125
126
 
@@ -127,20 +128,49 @@ class ParentTest < ActsAsDatedDetailTest
127
128
 
128
129
  def test_default_value_of_currently_effective_timestamp
129
130
  now = Time.now
130
- Time.stubs(:now).returns(now)
131
- pirate = Pirate.create!
132
- assert_equal Time.now, pirate.on
131
+ pirate = create_pirate([now])
132
+ assert_equal now, pirate.on
133
133
  end
134
134
 
135
135
  def test_setting_value_of_currently_effective_timestamp
136
- now = Time.now
137
- Time.stubs(:now).returns(now)
138
- pirate = Pirate.create!
136
+ pirate = create_pirate
139
137
  one_month_ago = Time.now - 1.month
140
138
  pirate.on = one_month_ago
141
139
  assert_equal one_month_ago, pirate.on
142
140
  end
143
141
 
142
+ # Determining if instance is tracking latest history
143
+
144
+ def test_tracks_latest_history_by_default
145
+ pirate = create_pirate
146
+ assert pirate.current?
147
+ end
148
+
149
+ def test_does_not_track_latest_history_when_currently_effective_timestamp_set
150
+ [1.day.ago, Time.now].each do |time|
151
+ pirate = create_pirate
152
+ pirate.on = time
153
+ assert !pirate.current?
154
+ end
155
+ end
156
+
157
+ def test_does_not_track_latest_history_when_currently_effective_timestamp_reset_to_now
158
+ pirate = create_pirate
159
+ pirate.on = 1.day.ago
160
+ pirate.on = Time.now
161
+ assert !pirate.current?
162
+ end
163
+
164
+ # Forcing instance to track latest history again
165
+
166
+ def test_tracks_latest_history_again
167
+ pirate = create_pirate([1.year.ago, 6.months.ago, 1.month.ago])
168
+ pirate.on = 6.months.ago
169
+ pirate.current!
170
+ assert pirate.current?
171
+ assert_equal catchphrase(1.month.ago), pirate.catchphrase
172
+ end
173
+
144
174
  # Tracked Attribute Retrieval
145
175
 
146
176
  def test_tracked_attribute_for_oldest_timestamp_set_by_instance_method
@@ -160,40 +190,41 @@ class ParentTest < ActsAsDatedDetailTest
160
190
  pirate.on = 2.weeks.ago
161
191
  assert_equal catchphrase(1.month.ago), pirate.catchphrase
162
192
  end
163
-
164
- # def test_start_on
165
- #
166
- # end
167
- #
168
- # def test_end_on
169
- #
170
- # end
171
- #
172
- # def test_end_on_for_last_dated_detail
173
- #
174
- # end
175
- #
176
- # def test_previous
177
- #
178
- # end
179
- #
180
- # def test_previous_for_first_dated_detail
181
- #
182
- # end
183
- #
184
- # def test_next
185
- #
186
- # end
187
- #
188
- # def test_next_for_last_dated_detail
189
- #
190
- # end
193
+
194
+ # Reloading
195
+
196
+ def test_reloading_when_tracking_latest_history
197
+ pirate = create_pirate([1.hour.ago])
198
+ same_pirate = Pirate.find(pirate.id)
199
+ new_ruthlessness = 999 #same_pirate.ruthlessness + 1
200
+ same_pirate.update_attribute(:ruthlessness, new_ruthlessness)
201
+ flunk 'Pirate must be tracking latest history' unless pirate.current?
202
+ pirate.reload
203
+ assert_equal new_ruthlessness, pirate.ruthlessness
204
+ end
205
+
206
+ def test_reloading_when_not_tracking_latest_history
207
+ pirate = create_pirate([6.months.ago, 1.hour.ago])
208
+ pirate.on = 5.months.ago
209
+ ruthlessness = pirate.ruthlessness
210
+ same_pirate = Pirate.find(pirate.id)
211
+ same_pirate.update_attribute(:ruthlessness, same_pirate.ruthlessness + 1)
212
+ flunk 'Pirate must not be tracking latest history' if pirate.current?
213
+ pirate.reload
214
+ assert_equal ruthlessness, pirate.ruthlessness
215
+ end
216
+
217
+ def test_reloading_returns_self
218
+ # #reload is aliased. Test that it returns correctly
219
+ pirate = create_pirate
220
+ assert_equal pirate, pirate.reload
221
+ end
191
222
 
192
223
  # Tracked Attribute Methods
193
224
 
194
225
  def test_read_tracked_attributes
195
226
  # Ensure value from dated_detail is returned
196
- pirate = Pirate.create!
227
+ pirate = create_pirate
197
228
  dated_detail = pirate.dated_detail
198
229
  pirate.stubs(:dated_detail).returns(dated_detail)
199
230
  PirateDatedDetail.tracked_attributes.each do |attribute|
@@ -205,58 +236,50 @@ class ParentTest < ActsAsDatedDetailTest
205
236
  end
206
237
 
207
238
  def test_write_tracked_attributes
208
- pirate = Pirate.create!
239
+ pirate = create_pirate
209
240
  PirateDatedDetail.tracked_attributes.each do |attribute|
210
241
  value = 10
211
242
  pirate.send("#{attribute}=", value)
243
+ assert_equal value, pirate.attributes[attribute]
212
244
  assert_equal value, pirate.dated_detail.send(attribute)
213
245
  end
214
246
  end
215
247
 
216
248
  # Updating Attributes
217
249
 
250
+ def test_updating_tracked_attribute_updates_currently_effective_timestamp
251
+ pirate = create_pirate([1.year.ago])
252
+ pirate.update_attribute(:catchphrase, 'Yar!')
253
+ assert_equal Time.now, pirate.on
254
+ end
255
+
218
256
  def test_updating_tracked_integer_attribute
219
- now = Time.now
220
- Time.stubs(:now).returns(now - 1.year)
221
- pirate = Pirate.create!
222
- Time.stubs(:now).returns(now)
257
+ pirate = create_pirate([1.year.ago])
223
258
  pirate.update_attribute(:ruthlessness, 10)
224
259
  assert_equal 2, pirate.dated_details.count
225
260
  end
226
261
 
227
262
  def test_updating_tracked_string_attribute
228
- now = Time.now
229
- Time.stubs(:now).returns(now - 1.year)
230
- pirate = Pirate.create!
231
- Time.stubs(:now).returns(now)
263
+ pirate = create_pirate([1.year.ago])
232
264
  pirate.update_attribute(:catchphrase, 'Yar!')
233
265
  assert_equal 2, pirate.dated_details.count
234
266
  end
235
267
 
236
268
  def test_updating_tracked_datetime_attribute
237
- now = Time.now
238
- Time.stubs(:now).returns(now - 1.year)
239
- pirate = create_pirate
240
- Time.stubs(:now).returns(now)
269
+ pirate = create_pirate([1.year.ago])
241
270
  pirate.update_attributes(:birth_date => pirate.birth_date + 1.day)
242
271
  assert_equal 2, pirate.dated_details.count
243
272
  end
244
273
 
245
274
  def test_updating_tracked_multiparameter_attribute
246
- now = Time.now
247
- Time.stubs(:now).returns(now - 1.year)
248
- pirate = create_pirate
249
- Time.stubs(:now).returns(now)
275
+ pirate = create_pirate([1.year.ago])
250
276
  new_birth_date = pirate.birth_date + 1.day
251
277
  pirate.update_attributes('birth_date(1i)' => "#{new_birth_date.year}", 'birth_date(2i)' => "#{new_birth_date.month}", 'birth_date(3i)' => "#{new_birth_date.day}")
252
278
  assert_equal 2, pirate.dated_details.count
253
279
  end
254
280
 
255
281
  def test_updating_untracked_attribute
256
- now = Time.now
257
- Time.stubs(:now).returns(now - 1.year)
258
- pirate = Pirate.create!
259
- Time.stubs(:now).returns(now)
282
+ pirate = create_pirate([1.year.ago])
260
283
  pirate.update_attribute(:name, 'Long John Silver')
261
284
  assert_equal 1, pirate.dated_details.count
262
285
  end
@@ -281,29 +304,26 @@ class DatedDetailTest < ActsAsDatedDetailTest
281
304
  # Creation
282
305
 
283
306
  def test_initial_start_on_value
284
- pirate = Pirate.create!
307
+ pirate = create_pirate
285
308
  assert_equal Time.now.to_i, PirateDatedDetail.first.start_on.to_i
286
309
  end
287
310
 
288
311
  def test_initial_end_on_value
289
- pirate = Pirate.create!
312
+ pirate = create_pirate
290
313
  assert_nil PirateDatedDetail.first.end_on
291
314
  end
292
315
 
293
316
  # Updating
294
317
 
295
318
  def test_updating
296
- now = Time.now
297
- Time.stubs(:now).returns(now - 1.year)
298
- pirate = Pirate.create!
299
- Time.stubs(:now).returns(now)
319
+ pirate = create_pirate([Time.now - 1.year])
300
320
 
301
321
  dated_detail = pirate.dated_detail
302
322
  original_dated_detail = dated_detail.class.find(dated_detail.id) # Cloning would keep millisecond parts of time which would make later comparisons harder
303
323
 
304
324
  dated_detail.update_attribute(:ruthlessness, 10)
305
325
 
306
- assert_equal now.to_i, dated_detail.start_on.to_i
326
+ assert_equal Time.now.to_i, dated_detail.start_on.to_i
307
327
  assert_nil dated_detail.end_on
308
328
 
309
329
  previous_dated_detail = PirateDatedDetail.find_by_start_on(original_dated_detail.start_on)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: acts_as_dated_detail
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paul Gillard
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2010-01-02 00:00:00 +00:00
12
+ date: 2010-01-05 00:00:00 +00:00
13
13
  default_executable:
14
14
  dependencies: []
15
15