acts_as_dated_detail 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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