activesupport 6.0.4 → 6.1.4

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activesupport might be problematic. Click here for more details.

Files changed (130) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +388 -460
  3. data/MIT-LICENSE +1 -1
  4. data/lib/active_support/array_inquirer.rb +4 -2
  5. data/lib/active_support/backtrace_cleaner.rb +3 -3
  6. data/lib/active_support/benchmarkable.rb +1 -1
  7. data/lib/active_support/cache/file_store.rb +3 -3
  8. data/lib/active_support/cache/mem_cache_store.rb +28 -18
  9. data/lib/active_support/cache/memory_store.rb +46 -26
  10. data/lib/active_support/cache/redis_cache_store.rb +25 -25
  11. data/lib/active_support/cache/strategy/local_cache.rb +20 -5
  12. data/lib/active_support/cache.rb +87 -40
  13. data/lib/active_support/callbacks.rb +65 -56
  14. data/lib/active_support/concern.rb +46 -2
  15. data/lib/active_support/configurable.rb +3 -3
  16. data/lib/active_support/configuration_file.rb +51 -0
  17. data/lib/active_support/core_ext/benchmark.rb +2 -2
  18. data/lib/active_support/core_ext/class/attribute.rb +34 -44
  19. data/lib/active_support/core_ext/class/subclasses.rb +17 -38
  20. data/lib/active_support/core_ext/date/conversions.rb +2 -1
  21. data/lib/active_support/core_ext/date_and_time/calculations.rb +13 -0
  22. data/lib/active_support/core_ext/date_and_time/compatibility.rb +15 -0
  23. data/lib/active_support/core_ext/enumerable.rb +76 -4
  24. data/lib/active_support/core_ext/hash/conversions.rb +2 -2
  25. data/lib/active_support/core_ext/hash/deep_transform_values.rb +1 -1
  26. data/lib/active_support/core_ext/hash/keys.rb +1 -1
  27. data/lib/active_support/core_ext/hash/slice.rb +3 -2
  28. data/lib/active_support/core_ext/load_error.rb +1 -1
  29. data/lib/active_support/core_ext/marshal.rb +2 -0
  30. data/lib/active_support/core_ext/module/attr_internal.rb +2 -2
  31. data/lib/active_support/core_ext/module/attribute_accessors.rb +23 -29
  32. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +8 -4
  33. data/lib/active_support/core_ext/module/concerning.rb +8 -2
  34. data/lib/active_support/core_ext/module/delegation.rb +38 -28
  35. data/lib/active_support/core_ext/module/introspection.rb +1 -25
  36. data/lib/active_support/core_ext/name_error.rb +29 -2
  37. data/lib/active_support/core_ext/numeric/conversions.rb +22 -18
  38. data/lib/active_support/core_ext/object/deep_dup.rb +1 -1
  39. data/lib/active_support/core_ext/object/json.rb +12 -1
  40. data/lib/active_support/core_ext/object/try.rb +2 -2
  41. data/lib/active_support/core_ext/range/compare_range.rb +9 -3
  42. data/lib/active_support/core_ext/range/include_time_with_zone.rb +8 -3
  43. data/lib/active_support/core_ext/regexp.rb +8 -1
  44. data/lib/active_support/core_ext/string/access.rb +5 -24
  45. data/lib/active_support/core_ext/string/conversions.rb +1 -0
  46. data/lib/active_support/core_ext/string/inflections.rb +38 -4
  47. data/lib/active_support/core_ext/string/inquiry.rb +1 -0
  48. data/lib/active_support/core_ext/string/multibyte.rb +2 -2
  49. data/lib/active_support/core_ext/string/output_safety.rb +3 -4
  50. data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -2
  51. data/lib/active_support/core_ext/symbol/starts_ends_with.rb +14 -0
  52. data/lib/active_support/core_ext/symbol.rb +3 -0
  53. data/lib/active_support/core_ext/time/calculations.rb +17 -0
  54. data/lib/active_support/core_ext/time/conversions.rb +2 -0
  55. data/lib/active_support/core_ext/uri.rb +5 -1
  56. data/lib/active_support/core_ext.rb +1 -1
  57. data/lib/active_support/current_attributes/test_helper.rb +13 -0
  58. data/lib/active_support/current_attributes.rb +8 -2
  59. data/lib/active_support/dependencies.rb +37 -18
  60. data/lib/active_support/deprecation/behaviors.rb +15 -2
  61. data/lib/active_support/deprecation/disallowed.rb +56 -0
  62. data/lib/active_support/deprecation/instance_delegator.rb +0 -1
  63. data/lib/active_support/deprecation/method_wrappers.rb +3 -2
  64. data/lib/active_support/deprecation/proxy_wrappers.rb +2 -2
  65. data/lib/active_support/deprecation/reporting.rb +50 -7
  66. data/lib/active_support/deprecation.rb +6 -1
  67. data/lib/active_support/descendants_tracker.rb +6 -2
  68. data/lib/active_support/duration/iso8601_serializer.rb +15 -9
  69. data/lib/active_support/duration.rb +71 -22
  70. data/lib/active_support/encrypted_file.rb +19 -2
  71. data/lib/active_support/environment_inquirer.rb +20 -0
  72. data/lib/active_support/evented_file_update_checker.rb +69 -133
  73. data/lib/active_support/fork_tracker.rb +64 -0
  74. data/lib/active_support/gem_version.rb +1 -1
  75. data/lib/active_support/hash_with_indifferent_access.rb +48 -24
  76. data/lib/active_support/i18n_railtie.rb +14 -19
  77. data/lib/active_support/inflector/inflections.rb +1 -2
  78. data/lib/active_support/inflector/methods.rb +35 -31
  79. data/lib/active_support/inflector/transliterate.rb +4 -4
  80. data/lib/active_support/json/decoding.rb +4 -4
  81. data/lib/active_support/json/encoding.rb +5 -1
  82. data/lib/active_support/key_generator.rb +1 -1
  83. data/lib/active_support/locale/en.yml +7 -3
  84. data/lib/active_support/log_subscriber.rb +8 -0
  85. data/lib/active_support/logger.rb +1 -1
  86. data/lib/active_support/logger_silence.rb +2 -26
  87. data/lib/active_support/logger_thread_safe_level.rb +34 -12
  88. data/lib/active_support/message_encryptor.rb +4 -7
  89. data/lib/active_support/message_verifier.rb +5 -5
  90. data/lib/active_support/messages/rotation_configuration.rb +2 -1
  91. data/lib/active_support/messages/rotator.rb +6 -5
  92. data/lib/active_support/multibyte/chars.rb +4 -42
  93. data/lib/active_support/multibyte/unicode.rb +9 -83
  94. data/lib/active_support/notifications/fanout.rb +23 -8
  95. data/lib/active_support/notifications/instrumenter.rb +6 -15
  96. data/lib/active_support/notifications.rb +32 -5
  97. data/lib/active_support/number_helper/number_converter.rb +1 -1
  98. data/lib/active_support/number_helper/number_to_human_converter.rb +1 -1
  99. data/lib/active_support/number_helper/number_to_human_size_converter.rb +1 -1
  100. data/lib/active_support/number_helper/number_to_rounded_converter.rb +9 -5
  101. data/lib/active_support/number_helper/rounding_helper.rb +12 -28
  102. data/lib/active_support/number_helper.rb +29 -14
  103. data/lib/active_support/option_merger.rb +2 -1
  104. data/lib/active_support/ordered_options.rb +8 -2
  105. data/lib/active_support/parameter_filter.rb +16 -11
  106. data/lib/active_support/per_thread_registry.rb +1 -1
  107. data/lib/active_support/rails.rb +1 -4
  108. data/lib/active_support/railtie.rb +23 -1
  109. data/lib/active_support/rescuable.rb +4 -4
  110. data/lib/active_support/secure_compare_rotator.rb +51 -0
  111. data/lib/active_support/security_utils.rb +19 -12
  112. data/lib/active_support/string_inquirer.rb +4 -2
  113. data/lib/active_support/subscriber.rb +12 -7
  114. data/lib/active_support/tagged_logging.rb +29 -4
  115. data/lib/active_support/testing/assertions.rb +18 -11
  116. data/lib/active_support/testing/parallelization/server.rb +78 -0
  117. data/lib/active_support/testing/parallelization/worker.rb +100 -0
  118. data/lib/active_support/testing/parallelization.rb +12 -95
  119. data/lib/active_support/testing/time_helpers.rb +40 -3
  120. data/lib/active_support/time_with_zone.rb +67 -43
  121. data/lib/active_support/values/time_zone.rb +20 -10
  122. data/lib/active_support/xml_mini/rexml.rb +8 -1
  123. data/lib/active_support.rb +13 -1
  124. metadata +33 -35
  125. data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -5
  126. data/lib/active_support/core_ext/hash/compact.rb +0 -5
  127. data/lib/active_support/core_ext/hash/transform_values.rb +0 -5
  128. data/lib/active_support/core_ext/module/reachable.rb +0 -6
  129. data/lib/active_support/core_ext/numeric/inquiry.rb +0 -5
  130. data/lib/active_support/core_ext/range/include_range.rb +0 -9
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "active_support/core_ext/enumerable"
4
+
3
5
  module ActiveSupport
4
6
  module Testing
5
7
  module Assertions
@@ -30,6 +32,8 @@ module ActiveSupport
30
32
  # end
31
33
  def assert_nothing_raised
32
34
  yield
35
+ rescue => error
36
+ raise Minitest::UnexpectedError.new(error)
33
37
  end
34
38
 
35
39
  # Test numeric difference between the return value of an expression as a
@@ -87,7 +91,7 @@ module ActiveSupport
87
91
  else
88
92
  difference = args[0] || 1
89
93
  message = args[1]
90
- Hash[Array(expression).map { |e| [e, difference] }]
94
+ Array(expression).index_with(difference)
91
95
  end
92
96
 
93
97
  exps = expressions.keys.map { |e|
@@ -95,7 +99,7 @@ module ActiveSupport
95
99
  }
96
100
  before = exps.map(&:call)
97
101
 
98
- retval = yield
102
+ retval = assert_nothing_raised(&block)
99
103
 
100
104
  expressions.zip(exps, before) do |(code, diff), exp, before_value|
101
105
  error = "#{code.inspect} didn't change by #{diff}"
@@ -172,10 +176,10 @@ module ActiveSupport
172
176
  exp = expression.respond_to?(:call) ? expression : -> { eval(expression.to_s, block.binding) }
173
177
 
174
178
  before = exp.call
175
- retval = yield
179
+ retval = assert_nothing_raised(&block)
176
180
 
177
181
  unless from == UNTRACKED
178
- error = "#{expression.inspect} isn't #{from.inspect}"
182
+ error = "Expected change from #{from.inspect}"
179
183
  error = "#{message}.\n#{error}" if message
180
184
  assert from === before, error
181
185
  end
@@ -185,12 +189,10 @@ module ActiveSupport
185
189
  error = "#{expression.inspect} didn't change"
186
190
  error = "#{error}. It was already #{to}" if before == to
187
191
  error = "#{message}.\n#{error}" if message
188
- assert before != after, error
192
+ assert_not_equal before, after, error
189
193
 
190
194
  unless to == UNTRACKED
191
- error = "#{expression.inspect} didn't change to as expected\n"
192
- error = "#{error}Expected: #{to.inspect}\n"
193
- error = "#{error} Actual: #{after.inspect}"
195
+ error = "Expected change to #{to}\n"
194
196
  error = "#{message}.\n#{error}" if message
195
197
  assert to === after, error
196
198
  end
@@ -214,12 +216,17 @@ module ActiveSupport
214
216
  exp = expression.respond_to?(:call) ? expression : -> { eval(expression.to_s, block.binding) }
215
217
 
216
218
  before = exp.call
217
- retval = yield
219
+ retval = assert_nothing_raised(&block)
218
220
  after = exp.call
219
221
 
220
- error = "#{expression.inspect} did change to #{after}"
222
+ error = "#{expression.inspect} changed"
221
223
  error = "#{message}.\n#{error}" if message
222
- assert before == after, error
224
+
225
+ if before.nil?
226
+ assert_nil after, error
227
+ else
228
+ assert_equal before, after, error
229
+ end
223
230
 
224
231
  retval
225
232
  end
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "drb"
4
+ require "drb/unix" unless Gem.win_platform?
5
+
6
+ module ActiveSupport
7
+ module Testing
8
+ class Parallelization # :nodoc:
9
+ class Server
10
+ include DRb::DRbUndumped
11
+
12
+ def initialize
13
+ @queue = Queue.new
14
+ @active_workers = Concurrent::Map.new
15
+ @in_flight = Concurrent::Map.new
16
+ end
17
+
18
+ def record(reporter, result)
19
+ raise DRb::DRbConnError if result.is_a?(DRb::DRbUnknown)
20
+
21
+ @in_flight.delete([result.klass, result.name])
22
+
23
+ reporter.synchronize do
24
+ reporter.record(result)
25
+ end
26
+ end
27
+
28
+ def <<(o)
29
+ o[2] = DRbObject.new(o[2]) if o
30
+ @queue << o
31
+ end
32
+
33
+ def pop
34
+ if test = @queue.pop
35
+ @in_flight[[test[0].to_s, test[1]]] = test
36
+ test
37
+ end
38
+ end
39
+
40
+ def start_worker(worker_id)
41
+ @active_workers[worker_id] = true
42
+ end
43
+
44
+ def stop_worker(worker_id)
45
+ @active_workers.delete(worker_id)
46
+ end
47
+
48
+ def active_workers?
49
+ @active_workers.size > 0
50
+ end
51
+
52
+ def shutdown
53
+ # Wait for initial queue to drain
54
+ while @queue.length != 0
55
+ sleep 0.1
56
+ end
57
+
58
+ @queue.close
59
+
60
+ # Wait until all workers have finished
61
+ while active_workers?
62
+ sleep 0.1
63
+ end
64
+
65
+ @in_flight.values.each do |(klass, name, reporter)|
66
+ result = Minitest::Result.from(klass.new(name))
67
+ error = RuntimeError.new("result not reported")
68
+ error.set_backtrace([""])
69
+ result.failures << Minitest::UnexpectedError.new(error)
70
+ reporter.synchronize do
71
+ reporter.record(result)
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,100 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveSupport
4
+ module Testing
5
+ class Parallelization # :nodoc:
6
+ class Worker
7
+ def initialize(number, url)
8
+ @id = SecureRandom.uuid
9
+ @number = number
10
+ @url = url
11
+ @setup_exception = nil
12
+ end
13
+
14
+ def start
15
+ fork do
16
+ set_process_title("(starting)")
17
+
18
+ DRb.stop_service
19
+
20
+ @queue = DRbObject.new_with_uri(@url)
21
+ @queue.start_worker(@id)
22
+
23
+ begin
24
+ after_fork
25
+ rescue => @setup_exception; end
26
+
27
+ work_from_queue
28
+ ensure
29
+ set_process_title("(stopping)")
30
+
31
+ run_cleanup
32
+ @queue.stop_worker(@id)
33
+ end
34
+ end
35
+
36
+ def work_from_queue
37
+ while job = @queue.pop
38
+ perform_job(job)
39
+ end
40
+ end
41
+
42
+ def perform_job(job)
43
+ klass = job[0]
44
+ method = job[1]
45
+ reporter = job[2]
46
+
47
+ set_process_title("#{klass}##{method}")
48
+
49
+ result = klass.with_info_handler reporter do
50
+ Minitest.run_one_method(klass, method)
51
+ end
52
+
53
+ safe_record(reporter, result)
54
+ end
55
+
56
+ def safe_record(reporter, result)
57
+ add_setup_exception(result) if @setup_exception
58
+
59
+ begin
60
+ @queue.record(reporter, result)
61
+ rescue DRb::DRbConnError
62
+ result.failures.map! do |failure|
63
+ if failure.respond_to?(:error)
64
+ # minitest >5.14.0
65
+ error = DRb::DRbRemoteError.new(failure.error)
66
+ else
67
+ error = DRb::DRbRemoteError.new(failure.exception)
68
+ end
69
+ Minitest::UnexpectedError.new(error)
70
+ end
71
+ @queue.record(reporter, result)
72
+ end
73
+
74
+ set_process_title("(idle)")
75
+ end
76
+
77
+ def after_fork
78
+ Parallelization.after_fork_hooks.each do |cb|
79
+ cb.call(@number)
80
+ end
81
+ end
82
+
83
+ def run_cleanup
84
+ Parallelization.run_cleanup_hooks.each do |cb|
85
+ cb.call(@number)
86
+ end
87
+ end
88
+
89
+ private
90
+ def add_setup_exception(result)
91
+ result.failures.prepend Minitest::UnexpectedError.new(@setup_exception)
92
+ end
93
+
94
+ def set_process_title(status)
95
+ Process.setproctitle("Rails test worker #{@number} - #{status}")
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
@@ -3,37 +3,12 @@
3
3
  require "drb"
4
4
  require "drb/unix" unless Gem.win_platform?
5
5
  require "active_support/core_ext/module/attribute_accessors"
6
+ require "active_support/testing/parallelization/server"
7
+ require "active_support/testing/parallelization/worker"
6
8
 
7
9
  module ActiveSupport
8
10
  module Testing
9
11
  class Parallelization # :nodoc:
10
- class Server
11
- include DRb::DRbUndumped
12
-
13
- def initialize
14
- @queue = Queue.new
15
- end
16
-
17
- def record(reporter, result)
18
- raise DRb::DRbConnError if result.is_a?(DRb::DRbUnknown)
19
-
20
- reporter.synchronize do
21
- reporter.record(result)
22
- end
23
- end
24
-
25
- def <<(o)
26
- o[2] = DRbObject.new(o[2]) if o
27
- @queue << o
28
- end
29
-
30
- def length
31
- @queue.length
32
- end
33
-
34
- def pop; @queue.pop; end
35
- end
36
-
37
12
  @@after_fork_hooks = []
38
13
 
39
14
  def self.after_fork_hook(&blk)
@@ -50,85 +25,27 @@ module ActiveSupport
50
25
 
51
26
  cattr_reader :run_cleanup_hooks
52
27
 
53
- def initialize(queue_size)
54
- @queue_size = queue_size
55
- @queue = Server.new
56
- @pool = []
57
-
58
- @url = DRb.start_service("drbunix:", @queue).uri
59
- end
60
-
61
- def after_fork(worker)
62
- self.class.after_fork_hooks.each do |cb|
63
- cb.call(worker)
64
- end
65
- end
66
-
67
- def run_cleanup(worker)
68
- self.class.run_cleanup_hooks.each do |cb|
69
- cb.call(worker)
70
- end
28
+ def initialize(worker_count)
29
+ @worker_count = worker_count
30
+ @queue_server = Server.new
31
+ @worker_pool = []
32
+ @url = DRb.start_service("drbunix:", @queue_server).uri
71
33
  end
72
34
 
73
35
  def start
74
- @pool = @queue_size.times.map do |worker|
75
- fork do
76
- DRb.stop_service
77
-
78
- begin
79
- after_fork(worker)
80
- rescue => setup_exception; end
81
-
82
- queue = DRbObject.new_with_uri(@url)
83
-
84
- while job = queue.pop
85
- klass = job[0]
86
- method = job[1]
87
- reporter = job[2]
88
- result = klass.with_info_handler reporter do
89
- Minitest.run_one_method(klass, method)
90
- end
91
-
92
- add_setup_exception(result, setup_exception) if setup_exception
93
-
94
- begin
95
- queue.record(reporter, result)
96
- rescue DRb::DRbConnError
97
- result.failures.map! do |failure|
98
- if failure.respond_to?(:error)
99
- # minitest >5.14.0
100
- error = DRb::DRbRemoteError.new(failure.error)
101
- else
102
- error = DRb::DRbRemoteError.new(failure.exception)
103
- end
104
- Minitest::UnexpectedError.new(error)
105
- end
106
- queue.record(reporter, result)
107
- end
108
- end
109
- ensure
110
- run_cleanup(worker)
111
- end
36
+ @worker_pool = @worker_count.times.map do |worker|
37
+ Worker.new(worker, @url).start
112
38
  end
113
39
  end
114
40
 
115
41
  def <<(work)
116
- @queue << work
42
+ @queue_server << work
117
43
  end
118
44
 
119
45
  def shutdown
120
- @queue_size.times { @queue << nil }
121
- @pool.each { |pid| Process.waitpid pid }
122
-
123
- if @queue.length > 0
124
- raise "Queue not empty, but all workers have finished. This probably means that a worker crashed and #{@queue.length} tests were missed."
125
- end
46
+ @queue_server.shutdown
47
+ @worker_pool.each { |pid| Process.waitpid pid }
126
48
  end
127
-
128
- private
129
- def add_setup_exception(result, setup_exception)
130
- result.failures.prepend Minitest::UnexpectedError.new(setup_exception)
131
- end
132
49
  end
133
50
  end
134
51
  end
@@ -6,6 +6,7 @@ require "concurrent/map"
6
6
 
7
7
  module ActiveSupport
8
8
  module Testing
9
+ # Manages stubs for TimeHelpers
9
10
  class SimpleStubs # :nodoc:
10
11
  Stub = Struct.new(:object, :method_name, :original_method)
11
12
 
@@ -13,6 +14,13 @@ module ActiveSupport
13
14
  @stubs = Concurrent::Map.new { |h, k| h[k] = {} }
14
15
  end
15
16
 
17
+ # Stubs object.method_name with the given block
18
+ # If the method is already stubbed, remove that stub
19
+ # so that removing this stub will restore the original implementation.
20
+ # Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
21
+ # target = Time.zone.local(2004, 11, 24, 1, 4, 44)
22
+ # simple_stubs.stub_object(Time, :now) { at(target.to_i) }
23
+ # Time.current # => Wed, 24 Nov 2004 01:04:44 EST -05:00
16
24
  def stub_object(object, method_name, &block)
17
25
  if stub = stubbing(object, method_name)
18
26
  unstub_object(stub)
@@ -26,6 +34,7 @@ module ActiveSupport
26
34
  object.define_singleton_method(method_name, &block)
27
35
  end
28
36
 
37
+ # Remove all object-method stubs held by this instance
29
38
  def unstub_all!
30
39
  @stubs.each_value do |object_stubs|
31
40
  object_stubs.each_value do |stub|
@@ -35,11 +44,19 @@ module ActiveSupport
35
44
  @stubs.clear
36
45
  end
37
46
 
47
+ # Returns the Stub for object#method_name
48
+ # (nil if it is not stubbed)
38
49
  def stubbing(object, method_name)
39
50
  @stubs[object.object_id][method_name]
40
51
  end
41
52
 
53
+ # Returns true if any stubs are set, false if there are none
54
+ def stubbed?
55
+ !@stubs.empty?
56
+ end
57
+
42
58
  private
59
+ # Restores the original object.method described by the Stub
43
60
  def unstub_object(stub)
44
61
  singleton_class = stub.object.singleton_class
45
62
  singleton_class.silence_redefinition_of_method stub.method_name
@@ -82,7 +99,7 @@ module ActiveSupport
82
99
  # The stubs are automatically removed at the end of the test.
83
100
  #
84
101
  # Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
85
- # travel_to Time.zone.local(2004, 11, 24, 01, 04, 44)
102
+ # travel_to Time.zone.local(2004, 11, 24, 1, 4, 44)
86
103
  # Time.current # => Wed, 24 Nov 2004 01:04:44 EST -05:00
87
104
  # Date.current # => Wed, 24 Nov 2004
88
105
  # DateTime.current # => Wed, 24 Nov 2004 01:04:44 -0500
@@ -104,7 +121,7 @@ module ActiveSupport
104
121
  # state at the end of the block:
105
122
  #
106
123
  # Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
107
- # travel_to Time.zone.local(2004, 11, 24, 01, 04, 44) do
124
+ # travel_to Time.zone.local(2004, 11, 24, 1, 4, 44) do
108
125
  # Time.current # => Wed, 24 Nov 2004 01:04:44 EST -05:00
109
126
  # end
110
127
  # Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
@@ -160,12 +177,32 @@ module ActiveSupport
160
177
  # +travel+, +travel_to+, and +freeze_time+.
161
178
  #
162
179
  # Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
163
- # travel_to Time.zone.local(2004, 11, 24, 01, 04, 44)
180
+ #
181
+ # travel_to Time.zone.local(2004, 11, 24, 1, 4, 44)
164
182
  # Time.current # => Wed, 24 Nov 2004 01:04:44 EST -05:00
183
+ #
165
184
  # travel_back
166
185
  # Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
186
+ #
187
+ # This method also accepts a block, which brings the stubs back at the end of the block:
188
+ #
189
+ # Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
190
+ #
191
+ # travel_to Time.zone.local(2004, 11, 24, 1, 4, 44)
192
+ # Time.current # => Wed, 24 Nov 2004 01:04:44 EST -05:00
193
+ #
194
+ # travel_back do
195
+ # Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
196
+ # end
197
+ #
198
+ # Time.current # => Wed, 24 Nov 2004 01:04:44 EST -05:00
167
199
  def travel_back
200
+ stubbed_time = Time.current if block_given? && simple_stubs.stubbed?
201
+
168
202
  simple_stubs.unstub_all!
203
+ yield if block_given?
204
+ ensure
205
+ travel_to stubbed_time if stubbed_time
169
206
  end
170
207
  alias_method :unfreeze_time, :travel_back
171
208