activesupport 4.0.13 → 4.1.0.beta1

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 (124) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +283 -508
  3. data/README.rdoc +1 -1
  4. data/lib/active_support.rb +7 -1
  5. data/lib/active_support/backtrace_cleaner.rb +5 -5
  6. data/lib/active_support/benchmarkable.rb +0 -10
  7. data/lib/active_support/cache.rb +62 -26
  8. data/lib/active_support/cache/file_store.rb +27 -22
  9. data/lib/active_support/cache/mem_cache_store.rb +2 -2
  10. data/lib/active_support/cache/memory_store.rb +1 -0
  11. data/lib/active_support/cache/strategy/local_cache.rb +3 -0
  12. data/lib/active_support/callbacks.rb +416 -245
  13. data/lib/active_support/concern.rb +13 -5
  14. data/lib/active_support/core_ext.rb +0 -1
  15. data/lib/active_support/core_ext/array.rb +0 -1
  16. data/lib/active_support/core_ext/array/access.rb +2 -0
  17. data/lib/active_support/core_ext/array/conversions.rb +2 -17
  18. data/lib/active_support/core_ext/array/grouping.rb +24 -12
  19. data/lib/active_support/core_ext/array/prepend_and_append.rb +2 -2
  20. data/lib/active_support/core_ext/class.rb +0 -1
  21. data/lib/active_support/core_ext/class/attribute.rb +1 -2
  22. data/lib/active_support/core_ext/class/attribute_accessors.rb +5 -169
  23. data/lib/active_support/core_ext/date/calculations.rb +10 -0
  24. data/lib/active_support/core_ext/date/conversions.rb +5 -6
  25. data/lib/active_support/core_ext/date/zones.rb +2 -33
  26. data/lib/active_support/core_ext/date_and_time/calculations.rb +30 -11
  27. data/lib/active_support/core_ext/date_and_time/zones.rb +41 -0
  28. data/lib/active_support/core_ext/date_time/calculations.rb +12 -25
  29. data/lib/active_support/core_ext/date_time/conversions.rb +2 -0
  30. data/lib/active_support/core_ext/date_time/zones.rb +3 -21
  31. data/lib/active_support/core_ext/hash.rb +0 -1
  32. data/lib/active_support/core_ext/hash/conversions.rb +6 -3
  33. data/lib/active_support/core_ext/hash/deep_merge.rb +11 -22
  34. data/lib/active_support/core_ext/hash/indifferent_access.rb +1 -0
  35. data/lib/active_support/core_ext/hash/keys.rb +27 -47
  36. data/lib/active_support/core_ext/kernel/reporting.rb +2 -6
  37. data/lib/active_support/core_ext/module.rb +1 -0
  38. data/lib/active_support/core_ext/module/attribute_accessors.rb +160 -14
  39. data/lib/active_support/core_ext/module/concerning.rb +135 -0
  40. data/lib/active_support/core_ext/module/delegation.rb +14 -4
  41. data/lib/active_support/core_ext/module/deprecation.rb +0 -2
  42. data/lib/active_support/core_ext/module/introspection.rb +0 -16
  43. data/lib/active_support/core_ext/module/method_transplanting.rb +11 -0
  44. data/lib/active_support/core_ext/numeric/time.rb +8 -0
  45. data/lib/active_support/core_ext/object.rb +1 -1
  46. data/lib/active_support/core_ext/object/blank.rb +1 -1
  47. data/lib/active_support/core_ext/object/deep_dup.rb +6 -6
  48. data/lib/active_support/core_ext/object/inclusion.rb +4 -15
  49. data/lib/active_support/core_ext/object/json.rb +197 -0
  50. data/lib/active_support/core_ext/object/to_json.rb +4 -26
  51. data/lib/active_support/core_ext/object/to_param.rb +58 -1
  52. data/lib/active_support/core_ext/object/to_query.rb +7 -56
  53. data/lib/active_support/core_ext/object/try.rb +1 -1
  54. data/lib/active_support/core_ext/range/each.rb +2 -1
  55. data/lib/active_support/core_ext/string/access.rb +31 -31
  56. data/lib/active_support/core_ext/string/conversions.rb +9 -8
  57. data/lib/active_support/core_ext/string/exclude.rb +3 -3
  58. data/lib/active_support/core_ext/string/filters.rb +14 -4
  59. data/lib/active_support/core_ext/string/inflections.rb +11 -9
  60. data/lib/active_support/core_ext/string/output_safety.rb +65 -24
  61. data/lib/active_support/core_ext/string/zones.rb +1 -0
  62. data/lib/active_support/core_ext/thread.rb +4 -4
  63. data/lib/active_support/core_ext/time/calculations.rb +10 -57
  64. data/lib/active_support/core_ext/time/conversions.rb +3 -1
  65. data/lib/active_support/core_ext/time/zones.rb +2 -21
  66. data/lib/active_support/dependencies.rb +29 -13
  67. data/lib/active_support/deprecation.rb +4 -4
  68. data/lib/active_support/deprecation/behaviors.rb +3 -3
  69. data/lib/active_support/duration.rb +5 -7
  70. data/lib/active_support/file_update_checker.rb +1 -1
  71. data/lib/active_support/hash_with_indifferent_access.rb +4 -9
  72. data/lib/active_support/i18n.rb +4 -4
  73. data/lib/active_support/i18n_railtie.rb +2 -6
  74. data/lib/active_support/inflections.rb +0 -1
  75. data/lib/active_support/inflector/inflections.rb +17 -17
  76. data/lib/active_support/inflector/methods.rb +34 -17
  77. data/lib/active_support/json/decoding.rb +14 -21
  78. data/lib/active_support/json/encoding.rb +113 -285
  79. data/lib/active_support/key_generator.rb +1 -1
  80. data/lib/active_support/lazy_load_hooks.rb +1 -1
  81. data/lib/active_support/log_subscriber/test_helper.rb +1 -1
  82. data/lib/active_support/logger.rb +1 -1
  83. data/lib/active_support/message_encryptor.rb +3 -3
  84. data/lib/active_support/message_verifier.rb +6 -1
  85. data/lib/active_support/multibyte/chars.rb +1 -2
  86. data/lib/active_support/multibyte/unicode.rb +27 -39
  87. data/lib/active_support/notifications.rb +3 -3
  88. data/lib/active_support/notifications/instrumenter.rb +2 -1
  89. data/lib/active_support/number_helper.rb +20 -311
  90. data/lib/active_support/number_helper/number_converter.rb +182 -0
  91. data/lib/active_support/number_helper/number_to_currency_converter.rb +46 -0
  92. data/lib/active_support/number_helper/number_to_delimited_converter.rb +21 -0
  93. data/lib/active_support/number_helper/number_to_human_converter.rb +66 -0
  94. data/lib/active_support/number_helper/number_to_human_size_converter.rb +58 -0
  95. data/lib/active_support/number_helper/number_to_percentage_converter.rb +12 -0
  96. data/lib/active_support/number_helper/number_to_phone_converter.rb +49 -0
  97. data/lib/active_support/number_helper/number_to_rounded_converter.rb +62 -0
  98. data/lib/active_support/option_merger.rb +1 -1
  99. data/lib/active_support/ordered_hash.rb +0 -8
  100. data/lib/active_support/ordered_options.rb +8 -0
  101. data/lib/active_support/per_thread_registry.rb +9 -8
  102. data/lib/active_support/subscriber.rb +26 -3
  103. data/lib/active_support/test_case.rb +9 -10
  104. data/lib/active_support/testing/assertions.rb +0 -30
  105. data/lib/active_support/testing/autorun.rb +2 -2
  106. data/lib/active_support/testing/declarative.rb +18 -8
  107. data/lib/active_support/testing/isolation.rb +13 -65
  108. data/lib/active_support/testing/setup_and_teardown.rb +17 -2
  109. data/lib/active_support/testing/tagged_logging.rb +1 -1
  110. data/lib/active_support/testing/time_helpers.rb +55 -0
  111. data/lib/active_support/time_with_zone.rb +4 -4
  112. data/lib/active_support/values/time_zone.rb +18 -15
  113. data/lib/active_support/version.rb +1 -1
  114. data/lib/active_support/xml_mini.rb +2 -4
  115. metadata +71 -61
  116. data/lib/active_support/basic_object.rb +0 -11
  117. data/lib/active_support/buffered_logger.rb +0 -21
  118. data/lib/active_support/core_ext/array/uniq_by.rb +0 -19
  119. data/lib/active_support/core_ext/hash/diff.rb +0 -14
  120. data/lib/active_support/core_ext/logger.rb +0 -67
  121. data/lib/active_support/core_ext/proc.rb +0 -17
  122. data/lib/active_support/core_ext/string/encoding.rb +0 -8
  123. data/lib/active_support/json/variable.rb +0 -18
  124. data/lib/active_support/testing/pending.rb +0 -14
@@ -12,7 +12,7 @@ module ActiveSupport
12
12
 
13
13
  private
14
14
  def method_missing(method, *arguments, &block)
15
- if arguments.first.is_a?(Proc)
15
+ if arguments.last.is_a?(Proc)
16
16
  proc = arguments.pop
17
17
  arguments << lambda { |*args| @options.deep_merge(proc.call(*args)) }
18
18
  else
@@ -28,14 +28,6 @@ module ActiveSupport
28
28
  coder.represent_seq '!omap', map { |k,v| { k => v } }
29
29
  end
30
30
 
31
- def select(*args, &block)
32
- dup.tap { |hash| hash.select!(*args, &block) }
33
- end
34
-
35
- def reject(*args, &block)
36
- dup.tap { |hash| hash.reject!(*args, &block) }
37
- end
38
-
39
31
  def nested_under_indifferent_access
40
32
  self
41
33
  end
@@ -40,6 +40,14 @@ module ActiveSupport
40
40
  end
41
41
  end
42
42
 
43
+ # +InheritableOptions+ provides a constructor to build an +OrderedOptions+
44
+ # hash inherited from another hash.
45
+ #
46
+ # Use this if you already have some hash and you want to create a new one based on it.
47
+ #
48
+ # h = ActiveSupport::InheritableOptions.new({ girl: 'Mary', boy: 'John' })
49
+ # h.girl # => 'Mary'
50
+ # h.boy # => 'John'
43
51
  class InheritableOptions < OrderedOptions
44
52
  def initialize(parent = nil)
45
53
  if parent.kind_of?(OrderedOptions)
@@ -32,21 +32,22 @@ module ActiveSupport
32
32
  #
33
33
  # If the class has an initializer, it must accept no arguments.
34
34
  module PerThreadRegistry
35
- protected
35
+ def self.extended(object)
36
+ object.instance_variable_set '@per_thread_registry_key', object.name.freeze
37
+ end
38
+
39
+ def instance
40
+ Thread.current[@per_thread_registry_key] ||= new
41
+ end
36
42
 
43
+ protected
37
44
  def method_missing(name, *args, &block) # :nodoc:
38
45
  # Caches the method definition as a singleton method of the receiver.
39
46
  define_singleton_method(name) do |*a, &b|
40
- per_thread_registry_instance.public_send(name, *a, &b)
47
+ instance.public_send(name, *a, &b)
41
48
  end
42
49
 
43
50
  send(name, *args, &block)
44
51
  end
45
-
46
- private
47
-
48
- def per_thread_registry_instance
49
- Thread.current[name] ||= new
50
- end
51
52
  end
52
53
  end
@@ -31,18 +31,41 @@ module ActiveSupport
31
31
 
32
32
  # Attach the subscriber to a namespace.
33
33
  def attach_to(namespace, subscriber=new, notifier=ActiveSupport::Notifications)
34
+ @namespace = namespace
35
+ @subscriber = subscriber
36
+ @notifier = notifier
37
+
34
38
  subscribers << subscriber
35
39
 
40
+ # Add event subscribers for all existing methods on the class.
36
41
  subscriber.public_methods(false).each do |event|
37
- next if %w{ start finish }.include?(event.to_s)
42
+ add_event_subscriber(event)
43
+ end
44
+ end
38
45
 
39
- notifier.subscribe("#{event}.#{namespace}", subscriber)
46
+ # Adds event subscribers for all new methods added to the class.
47
+ def method_added(event)
48
+ # Only public methods are added as subscribers, and only if a notifier
49
+ # has been set up. This means that subscribers will only be set up for
50
+ # classes that call #attach_to.
51
+ if public_method_defined?(event) && notifier
52
+ add_event_subscriber(event)
40
53
  end
41
54
  end
42
55
 
43
56
  def subscribers
44
57
  @@subscribers ||= []
45
58
  end
59
+
60
+ protected
61
+
62
+ attr_reader :subscriber, :notifier, :namespace
63
+
64
+ def add_event_subscriber(event)
65
+ return if %w{ start finish }.include?(event.to_s)
66
+
67
+ notifier.subscribe("#{event}.#{namespace}", subscriber)
68
+ end
46
69
  end
47
70
 
48
71
  def initialize
@@ -71,7 +94,7 @@ module ActiveSupport
71
94
  private
72
95
 
73
96
  def event_stack
74
- SubscriberQueueRegistry.get_queue(@queue_key)
97
+ SubscriberQueueRegistry.instance.get_queue(@queue_key)
75
98
  end
76
99
  end
77
100
 
@@ -1,13 +1,13 @@
1
1
  gem 'minitest' # make sure we get the gem, not stdlib
2
- require 'minitest/unit'
2
+ require 'minitest'
3
3
  require 'active_support/testing/tagged_logging'
4
4
  require 'active_support/testing/setup_and_teardown'
5
5
  require 'active_support/testing/assertions'
6
6
  require 'active_support/testing/deprecation'
7
- require 'active_support/testing/pending'
8
7
  require 'active_support/testing/declarative'
9
8
  require 'active_support/testing/isolation'
10
9
  require 'active_support/testing/constant_lookup'
10
+ require 'active_support/testing/time_helpers'
11
11
  require 'active_support/core_ext/kernel/reporting'
12
12
  require 'active_support/deprecation'
13
13
 
@@ -17,9 +17,10 @@ rescue LoadError
17
17
  end
18
18
 
19
19
  module ActiveSupport
20
- class TestCase < ::MiniTest::Unit::TestCase
21
- Assertion = MiniTest::Assertion
22
- alias_method :method_name, :__name__
20
+ class TestCase < ::Minitest::Test
21
+ Assertion = Minitest::Assertion
22
+
23
+ alias_method :method_name, :name
23
24
 
24
25
  $tags = {}
25
26
  def self.for_tag(tag)
@@ -27,16 +28,14 @@ module ActiveSupport
27
28
  end
28
29
 
29
30
  # FIXME: we have tests that depend on run order, we should fix that and
30
- # remove this method.
31
- def self.test_order # :nodoc:
32
- :sorted
33
- end
31
+ # remove this method call.
32
+ self.i_suck_and_my_tests_are_order_dependent!
34
33
 
35
34
  include ActiveSupport::Testing::TaggedLogging
36
35
  include ActiveSupport::Testing::SetupAndTeardown
37
36
  include ActiveSupport::Testing::Assertions
38
37
  include ActiveSupport::Testing::Deprecation
39
- include ActiveSupport::Testing::Pending
38
+ include ActiveSupport::Testing::TimeHelpers
40
39
  extend ActiveSupport::Testing::Declarative
41
40
 
42
41
  # test/unit backwards compatibility methods
@@ -92,36 +92,6 @@ module ActiveSupport
92
92
  def assert_no_difference(expression, message = nil, &block)
93
93
  assert_difference expression, 0, message, &block
94
94
  end
95
-
96
- # Test if an expression is blank. Passes if <tt>object.blank?</tt>
97
- # is +true+.
98
- #
99
- # assert_blank [] # => true
100
- # assert_blank [[]] # => [[]] is not blank
101
- #
102
- # An error message can be specified.
103
- #
104
- # assert_blank [], 'this should be blank'
105
- def assert_blank(object, message=nil)
106
- ActiveSupport::Deprecation.warn('"assert_blank" is deprecated. Please use "assert object.blank?" instead')
107
- message ||= "#{object.inspect} is not blank"
108
- assert object.blank?, message
109
- end
110
-
111
- # Test if an expression is not blank. Passes if <tt>object.present?</tt>
112
- # is +true+.
113
- #
114
- # assert_present({ data: 'x' }) # => true
115
- # assert_present({}) # => {} is blank
116
- #
117
- # An error message can be specified.
118
- #
119
- # assert_present({ data: 'x' }, 'this should not be blank')
120
- def assert_present(object, message=nil)
121
- ActiveSupport::Deprecation.warn('"assert_present" is deprecated. Please use "assert object.present?" instead')
122
- message ||= "#{object.inspect} is blank"
123
- assert object.present?, message
124
- end
125
95
  end
126
96
  end
127
97
  end
@@ -1,5 +1,5 @@
1
1
  gem 'minitest'
2
2
 
3
- require 'minitest/unit'
3
+ require 'minitest'
4
4
 
5
- MiniTest::Unit.autorun
5
+ Minitest.autorun
@@ -7,11 +7,18 @@ module ActiveSupport
7
7
 
8
8
  unless method_defined?(:describe)
9
9
  def self.describe(text)
10
- class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
11
- def self.name
12
- "#{text}"
13
- end
14
- RUBY_EVAL
10
+ if block_given?
11
+ super
12
+ else
13
+ message = "`describe` without a block is deprecated, please switch to: `def self.name; #{text.inspect}; end`\n"
14
+ ActiveSupport::Deprecation.warn message
15
+
16
+ class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
17
+ def self.name
18
+ "#{text}"
19
+ end
20
+ RUBY_EVAL
21
+ end
15
22
  end
16
23
  end
17
24
 
@@ -19,9 +26,12 @@ module ActiveSupport
19
26
  end
20
27
 
21
28
  unless defined?(Spec)
22
- # test "verify something" do
23
- # ...
24
- # end
29
+ # Helper to define a test method using a String. Under the hood, it replaces
30
+ # spaces with underscores and defines the test method.
31
+ #
32
+ # test "verify something" do
33
+ # ...
34
+ # end
25
35
  def test(name, &block)
26
36
  test_name = "test_#{name.gsub(/\s+/,'_')}".to_sym
27
37
  defined = instance_method(test_name) rescue false
@@ -1,60 +1,14 @@
1
1
  require 'rbconfig'
2
- require 'minitest/parallel_each'
3
2
 
4
3
  module ActiveSupport
5
4
  module Testing
6
- class RemoteError < StandardError
7
-
8
- attr_reader :message, :backtrace
9
-
10
- def initialize(exception)
11
- @message = "caught #{exception.class.name}: #{exception.message}"
12
- @backtrace = exception.backtrace
13
- end
14
- end
15
-
16
- class ProxyTestResult
17
- def initialize(calls = [])
18
- @calls = calls
19
- end
20
-
21
- def add_error(e)
22
- e = Test::Unit::Error.new(e.test_name, RemoteError.new(e.exception))
23
- @calls << [:add_error, e]
24
- end
25
-
26
- def __replay__(result)
27
- @calls.each do |name, args|
28
- result.send(name, *args)
29
- end
30
- end
31
-
32
- def marshal_dump
33
- @calls
34
- end
35
-
36
- def marshal_load(calls)
37
- initialize(calls)
38
- end
39
-
40
- def method_missing(name, *args)
41
- @calls << [name, args]
42
- end
43
-
44
- def info_signal
45
- Signal.list['INFO']
46
- end
47
- end
48
-
49
5
  module Isolation
50
6
  require 'thread'
51
7
 
52
8
  def self.included(klass) #:nodoc:
53
- klass.extend(Module.new {
54
- def test_methods
55
- ParallelEach.new super
56
- end
57
- })
9
+ klass.class_eval do
10
+ parallelize_me!
11
+ end
58
12
  end
59
13
 
60
14
  def self.forking_env?
@@ -72,16 +26,12 @@ module ActiveSupport
72
26
  end
73
27
  end
74
28
 
75
- def run(runner)
76
- _run_class_setup
77
-
78
- serialized = run_in_isolation do |isolated_runner|
79
- super(isolated_runner)
29
+ def run
30
+ serialized = run_in_isolation do
31
+ super
80
32
  end
81
33
 
82
- retval, proxy = Marshal.load(serialized)
83
- proxy.__replay__(runner)
84
- retval
34
+ Marshal.load(serialized)
85
35
  end
86
36
 
87
37
  module Forking
@@ -90,9 +40,8 @@ module ActiveSupport
90
40
 
91
41
  pid = fork do
92
42
  read.close
93
- proxy = ProxyTestResult.new
94
- retval = yield proxy
95
- write.puts [Marshal.dump([retval, proxy])].pack("m")
43
+ yield
44
+ write.puts [Marshal.dump(self.dup)].pack("m")
96
45
  exit!
97
46
  end
98
47
 
@@ -112,19 +61,18 @@ module ActiveSupport
112
61
  require "tempfile"
113
62
 
114
63
  if ENV["ISOLATION_TEST"]
115
- proxy = ProxyTestResult.new
116
- retval = yield proxy
64
+ yield
117
65
  File.open(ENV["ISOLATION_OUTPUT"], "w") do |file|
118
- file.puts [Marshal.dump([retval, proxy])].pack("m")
66
+ file.puts [Marshal.dump(self.dup)].pack("m")
119
67
  end
120
68
  exit!
121
69
  else
122
70
  Tempfile.open("isolation") do |tmpfile|
123
- ENV["ISOLATION_TEST"] = @method_name
71
+ ENV["ISOLATION_TEST"] = self.class.name
124
72
  ENV["ISOLATION_OUTPUT"] = tmpfile.path
125
73
 
126
74
  load_paths = $-I.map {|p| "-I\"#{File.expand_path(p)}\"" }.join(" ")
127
- `#{Gem.ruby} #{load_paths} #{$0} #{ORIG_ARGV.join(" ")} -t\"#{self.class}\"`
75
+ `#{Gem.ruby} #{load_paths} #{$0} #{ORIG_ARGV.join(" ")}`
128
76
 
129
77
  ENV.delete("ISOLATION_TEST")
130
78
  ENV.delete("ISOLATION_OUTPUT")
@@ -3,6 +3,19 @@ require 'active_support/callbacks'
3
3
 
4
4
  module ActiveSupport
5
5
  module Testing
6
+ # Adds support for +setup+ and +teardown+ callbacks.
7
+ # These callbacks serve as a replacement to overwriting the
8
+ # <tt>#setup</tt> and <tt>#teardown</tt> methods of your TestCase.
9
+ #
10
+ # class ExampleTest < ActiveSupport::TestCase
11
+ # setup do
12
+ # # ...
13
+ # end
14
+ #
15
+ # teardown do
16
+ # # ...
17
+ # end
18
+ # end
6
19
  module SetupAndTeardown
7
20
  extend ActiveSupport::Concern
8
21
 
@@ -12,21 +25,23 @@ module ActiveSupport
12
25
  end
13
26
 
14
27
  module ClassMethods
28
+ # Add a callback, which runs before <tt>TestCase#setup</tt>.
15
29
  def setup(*args, &block)
16
30
  set_callback(:setup, :before, *args, &block)
17
31
  end
18
32
 
33
+ # Add a callback, which runs after <tt>TestCase#teardown</tt>.
19
34
  def teardown(*args, &block)
20
35
  set_callback(:teardown, :after, *args, &block)
21
36
  end
22
37
  end
23
38
 
24
- def before_setup
39
+ def before_setup # :nodoc:
25
40
  super
26
41
  run_callbacks :setup
27
42
  end
28
43
 
29
- def after_teardown
44
+ def after_teardown # :nodoc:
30
45
  run_callbacks :teardown
31
46
  super
32
47
  end
@@ -7,7 +7,7 @@ module ActiveSupport
7
7
 
8
8
  def before_setup
9
9
  if tagged_logger
10
- heading = "#{self.class}: #{__name__}"
10
+ heading = "#{self.class}: #{name}"
11
11
  divider = '-' * heading.size
12
12
  tagged_logger.info divider
13
13
  tagged_logger.info heading
@@ -0,0 +1,55 @@
1
+ module ActiveSupport
2
+ module Testing
3
+ # Containing helpers that helps you test passage of time.
4
+ module TimeHelpers
5
+ # Change current time to the time in the future or in the past by a given time difference by
6
+ # stubbing +Time.now+ and +Date.today+. Note that the stubs are automatically removed
7
+ # at the end of each test.
8
+ #
9
+ # Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
10
+ # travel 1.day
11
+ # Time.current # => Sun, 10 Nov 2013 15:34:49 EST -05:00
12
+ # Date.current # => Sun, 10 Nov 2013
13
+ #
14
+ # This method also accepts a block, which will return the current time back to its original
15
+ # state at the end of the block:
16
+ #
17
+ # Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
18
+ # travel 1.day do
19
+ # User.create.created_at # => Sun, 10 Nov 2013 15:34:49 EST -05:00
20
+ # end
21
+ # Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
22
+ def travel(duration, &block)
23
+ travel_to Time.now + duration, &block
24
+ end
25
+
26
+ # Change current time to the given time by stubbing +Time.now+ and +Date.today+ to return the
27
+ # time or date passed into this method. Note that the stubs are automatically removed
28
+ # at the end of each test.
29
+ #
30
+ # Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
31
+ # travel_to Time.new(2004, 11, 24, 01, 04, 44)
32
+ # Time.current # => Wed, 24 Nov 2004 01:04:44 EST -05:00
33
+ # Date.current # => Wed, 24 Nov 2004
34
+ #
35
+ # This method also accepts a block, which will return the current time back to its original
36
+ # state at the end of the block:
37
+ #
38
+ # Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
39
+ # travel_to Time.new(2004, 11, 24, 01, 04, 44) do
40
+ # User.create.created_at # => Wed, 24 Nov 2004 01:04:44 EST -05:00
41
+ # end
42
+ # Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
43
+ def travel_to(date_or_time, &block)
44
+ Time.stubs now: date_or_time.to_time
45
+ Date.stubs today: date_or_time.to_date
46
+
47
+ if block_given?
48
+ block.call
49
+ Time.unstub :now
50
+ Date.unstub :today
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end