activesupport 4.2.0 → 5.0.0.1

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 (185) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +630 -220
  3. data/MIT-LICENSE +2 -2
  4. data/README.rdoc +2 -3
  5. data/lib/active_support/array_inquirer.rb +44 -0
  6. data/lib/active_support/backtrace_cleaner.rb +1 -1
  7. data/lib/active_support/benchmarkable.rb +1 -1
  8. data/lib/active_support/cache/file_store.rb +36 -22
  9. data/lib/active_support/cache/mem_cache_store.rb +63 -54
  10. data/lib/active_support/cache/memory_store.rb +16 -21
  11. data/lib/active_support/cache/null_store.rb +1 -4
  12. data/lib/active_support/cache/strategy/local_cache.rb +31 -20
  13. data/lib/active_support/cache.rb +73 -89
  14. data/lib/active_support/callbacks.rb +195 -155
  15. data/lib/active_support/concern.rb +2 -2
  16. data/lib/active_support/concurrency/latch.rb +7 -15
  17. data/lib/active_support/concurrency/share_lock.rb +186 -0
  18. data/lib/active_support/configurable.rb +1 -0
  19. data/lib/active_support/core_ext/array/access.rb +27 -1
  20. data/lib/active_support/core_ext/array/conversions.rb +6 -4
  21. data/lib/active_support/core_ext/array/grouping.rb +9 -18
  22. data/lib/active_support/core_ext/array/inquiry.rb +17 -0
  23. data/lib/active_support/core_ext/array/wrap.rb +5 -4
  24. data/lib/active_support/core_ext/array.rb +1 -0
  25. data/lib/active_support/core_ext/big_decimal/conversions.rb +8 -10
  26. data/lib/active_support/core_ext/class/attribute.rb +10 -9
  27. data/lib/active_support/core_ext/class/subclasses.rb +3 -4
  28. data/lib/active_support/core_ext/class.rb +0 -1
  29. data/lib/active_support/core_ext/date/blank.rb +12 -0
  30. data/lib/active_support/core_ext/date/calculations.rb +1 -1
  31. data/lib/active_support/core_ext/date/conversions.rb +13 -6
  32. data/lib/active_support/core_ext/date.rb +1 -1
  33. data/lib/active_support/core_ext/date_and_time/calculations.rb +109 -25
  34. data/lib/active_support/core_ext/date_and_time/compatibility.rb +18 -0
  35. data/lib/active_support/core_ext/date_and_time/zones.rb +3 -4
  36. data/lib/active_support/core_ext/date_time/blank.rb +12 -0
  37. data/lib/active_support/core_ext/date_time/calculations.rb +36 -10
  38. data/lib/active_support/core_ext/date_time/compatibility.rb +5 -0
  39. data/lib/active_support/core_ext/date_time/conversions.rb +2 -0
  40. data/lib/active_support/core_ext/date_time.rb +2 -1
  41. data/lib/active_support/core_ext/enumerable.rb +49 -5
  42. data/lib/active_support/core_ext/file/atomic.rb +30 -25
  43. data/lib/active_support/core_ext/hash/conversions.rb +23 -4
  44. data/lib/active_support/core_ext/hash/deep_merge.rb +1 -1
  45. data/lib/active_support/core_ext/hash/except.rb +9 -8
  46. data/lib/active_support/core_ext/hash/indifferent_access.rb +1 -1
  47. data/lib/active_support/core_ext/hash/keys.rb +23 -19
  48. data/lib/active_support/core_ext/hash/slice.rb +1 -1
  49. data/lib/active_support/core_ext/hash/transform_values.rb +11 -5
  50. data/lib/active_support/core_ext/integer/time.rb +1 -16
  51. data/lib/active_support/core_ext/kernel/concern.rb +2 -0
  52. data/lib/active_support/core_ext/kernel/debugger.rb +3 -10
  53. data/lib/active_support/core_ext/kernel/reporting.rb +2 -83
  54. data/lib/active_support/core_ext/kernel.rb +0 -1
  55. data/lib/active_support/core_ext/load_error.rb +4 -2
  56. data/lib/active_support/core_ext/marshal.rb +12 -11
  57. data/lib/active_support/core_ext/module/aliasing.rb +6 -1
  58. data/lib/active_support/core_ext/module/anonymous.rb +10 -1
  59. data/lib/active_support/core_ext/module/attr_internal.rb +2 -5
  60. data/lib/active_support/core_ext/module/attribute_accessors.rb +15 -15
  61. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +141 -0
  62. data/lib/active_support/core_ext/module/concerning.rb +4 -4
  63. data/lib/active_support/core_ext/module/delegation.rb +35 -25
  64. data/lib/active_support/core_ext/module/deprecation.rb +2 -2
  65. data/lib/active_support/core_ext/module/introspection.rb +4 -0
  66. data/lib/active_support/core_ext/module/method_transplanting.rb +3 -11
  67. data/lib/active_support/core_ext/module/qualified_const.rb +30 -12
  68. data/lib/active_support/core_ext/module/remove_method.rb +23 -0
  69. data/lib/active_support/core_ext/module.rb +1 -0
  70. data/lib/active_support/core_ext/name_error.rb +15 -2
  71. data/lib/active_support/core_ext/numeric/bytes.rb +20 -0
  72. data/lib/active_support/core_ext/numeric/conversions.rb +74 -64
  73. data/lib/active_support/core_ext/numeric/inquiry.rb +26 -0
  74. data/lib/active_support/core_ext/numeric/time.rb +24 -19
  75. data/lib/active_support/core_ext/numeric.rb +1 -0
  76. data/lib/active_support/core_ext/object/blank.rb +17 -5
  77. data/lib/active_support/core_ext/object/deep_dup.rb +10 -3
  78. data/lib/active_support/core_ext/object/duplicable.rb +8 -13
  79. data/lib/active_support/core_ext/object/inclusion.rb +2 -2
  80. data/lib/active_support/core_ext/object/instance_variables.rb +1 -1
  81. data/lib/active_support/core_ext/object/json.rb +15 -7
  82. data/lib/active_support/core_ext/object/to_query.rb +1 -1
  83. data/lib/active_support/core_ext/object/try.rb +68 -22
  84. data/lib/active_support/core_ext/object/with_options.rb +1 -1
  85. data/lib/active_support/core_ext/object.rb +0 -1
  86. data/lib/active_support/core_ext/range/conversions.rb +18 -6
  87. data/lib/active_support/core_ext/range/each.rb +16 -18
  88. data/lib/active_support/core_ext/range/include_range.rb +20 -20
  89. data/lib/active_support/core_ext/securerandom.rb +23 -0
  90. data/lib/active_support/core_ext/string/access.rb +1 -1
  91. data/lib/active_support/core_ext/string/behavior.rb +1 -1
  92. data/lib/active_support/core_ext/string/conversions.rb +4 -3
  93. data/lib/active_support/core_ext/string/filters.rb +5 -5
  94. data/lib/active_support/core_ext/string/inflections.rb +32 -5
  95. data/lib/active_support/core_ext/string/multibyte.rb +11 -7
  96. data/lib/active_support/core_ext/string/output_safety.rb +18 -16
  97. data/lib/active_support/core_ext/string/strip.rb +3 -6
  98. data/lib/active_support/core_ext/struct.rb +3 -6
  99. data/lib/active_support/core_ext/time/calculations.rb +36 -11
  100. data/lib/active_support/core_ext/time/compatibility.rb +5 -0
  101. data/lib/active_support/core_ext/time/conversions.rb +4 -2
  102. data/lib/active_support/core_ext/time/marshal.rb +2 -29
  103. data/lib/active_support/core_ext/time/zones.rb +36 -4
  104. data/lib/active_support/core_ext/time.rb +1 -1
  105. data/lib/active_support/core_ext/uri.rb +1 -3
  106. data/lib/active_support/core_ext.rb +2 -1
  107. data/lib/active_support/dependencies/interlock.rb +51 -0
  108. data/lib/active_support/dependencies.rb +87 -95
  109. data/lib/active_support/deprecation/behaviors.rb +16 -2
  110. data/lib/active_support/deprecation/method_wrappers.rb +42 -16
  111. data/lib/active_support/deprecation/proxy_wrappers.rb +47 -24
  112. data/lib/active_support/deprecation/reporting.rb +23 -5
  113. data/lib/active_support/deprecation.rb +1 -1
  114. data/lib/active_support/duration/iso8601_parser.rb +122 -0
  115. data/lib/active_support/duration/iso8601_serializer.rb +51 -0
  116. data/lib/active_support/duration.rb +55 -10
  117. data/lib/active_support/evented_file_update_checker.rb +194 -0
  118. data/lib/active_support/execution_wrapper.rb +117 -0
  119. data/lib/active_support/executor.rb +6 -0
  120. data/lib/active_support/file_update_checker.rb +23 -3
  121. data/lib/active_support/gem_version.rb +4 -4
  122. data/lib/active_support/hash_with_indifferent_access.rb +46 -13
  123. data/lib/active_support/i18n_railtie.rb +25 -4
  124. data/lib/active_support/inflector/inflections.rb +36 -5
  125. data/lib/active_support/inflector/methods.rb +97 -90
  126. data/lib/active_support/inflector/transliterate.rb +36 -21
  127. data/lib/active_support/json/decoding.rb +11 -10
  128. data/lib/active_support/json/encoding.rb +4 -49
  129. data/lib/active_support/key_generator.rb +7 -9
  130. data/lib/active_support/locale/en.yml +2 -0
  131. data/lib/active_support/log_subscriber/test_helper.rb +3 -3
  132. data/lib/active_support/log_subscriber.rb +1 -1
  133. data/lib/active_support/logger.rb +50 -1
  134. data/lib/active_support/logger_silence.rb +8 -4
  135. data/lib/active_support/logger_thread_safe_level.rb +31 -0
  136. data/lib/active_support/message_encryptor.rb +4 -4
  137. data/lib/active_support/message_verifier.rb +70 -8
  138. data/lib/active_support/multibyte/chars.rb +13 -4
  139. data/lib/active_support/multibyte/unicode.rb +44 -21
  140. data/lib/active_support/notifications/fanout.rb +6 -6
  141. data/lib/active_support/notifications/instrumenter.rb +20 -2
  142. data/lib/active_support/notifications.rb +2 -2
  143. data/lib/active_support/number_helper/number_to_currency_converter.rb +7 -9
  144. data/lib/active_support/number_helper/number_to_delimited_converter.rb +8 -3
  145. data/lib/active_support/number_helper/number_to_human_converter.rb +6 -4
  146. data/lib/active_support/number_helper/number_to_human_size_converter.rb +6 -2
  147. data/lib/active_support/number_helper/number_to_percentage_converter.rb +1 -1
  148. data/lib/active_support/number_helper/number_to_phone_converter.rb +11 -2
  149. data/lib/active_support/number_helper/number_to_rounded_converter.rb +30 -25
  150. data/lib/active_support/number_helper.rb +90 -67
  151. data/lib/active_support/ordered_hash.rb +1 -1
  152. data/lib/active_support/ordered_options.rb +15 -1
  153. data/lib/active_support/per_thread_registry.rb +8 -3
  154. data/lib/active_support/rails.rb +2 -2
  155. data/lib/active_support/railtie.rb +6 -1
  156. data/lib/active_support/reloader.rb +129 -0
  157. data/lib/active_support/rescuable.rb +93 -47
  158. data/lib/active_support/security_utils.rb +7 -0
  159. data/lib/active_support/string_inquirer.rb +1 -1
  160. data/lib/active_support/subscriber.rb +5 -10
  161. data/lib/active_support/tagged_logging.rb +3 -1
  162. data/lib/active_support/test_case.rb +15 -29
  163. data/lib/active_support/testing/assertions.rb +15 -13
  164. data/lib/active_support/testing/autorun.rb +8 -1
  165. data/lib/active_support/testing/deprecation.rb +9 -8
  166. data/lib/active_support/testing/file_fixtures.rb +34 -0
  167. data/lib/active_support/testing/isolation.rb +22 -8
  168. data/lib/active_support/testing/method_call_assertions.rb +41 -0
  169. data/lib/active_support/testing/stream.rb +42 -0
  170. data/lib/active_support/testing/time_helpers.rb +13 -10
  171. data/lib/active_support/time_with_zone.rb +135 -46
  172. data/lib/active_support/values/time_zone.rb +95 -47
  173. data/lib/active_support/values/unicode_tables.dat +0 -0
  174. data/lib/active_support/xml_mini/jdom.rb +7 -6
  175. data/lib/active_support/xml_mini/libxml.rb +2 -2
  176. data/lib/active_support/xml_mini/nokogiri.rb +2 -2
  177. data/lib/active_support/xml_mini/rexml.rb +7 -8
  178. data/lib/active_support/xml_mini.rb +22 -14
  179. data/lib/active_support.rb +20 -6
  180. metadata +33 -35
  181. data/lib/active_support/core_ext/big_decimal/yaml_conversions.rb +0 -14
  182. data/lib/active_support/core_ext/class/delegating_attributes.rb +0 -45
  183. data/lib/active_support/core_ext/date_time/zones.rb +0 -6
  184. data/lib/active_support/core_ext/object/itself.rb +0 -15
  185. data/lib/active_support/core_ext/thread.rb +0 -86
@@ -63,10 +63,10 @@ class Module
63
63
  #
64
64
  # == Mix-in noise exiled to its own file:
65
65
  #
66
- # Once our chunk of behavior starts pushing the scroll-to-understand it's
66
+ # Once our chunk of behavior starts pushing the scroll-to-understand-it
67
67
  # boundary, we give in and move it to a separate file. At this size, the
68
- # overhead feels in good proportion to the size of our extraction, despite
69
- # diluting our at-a-glance sense of how things really work.
68
+ # increased overhead can be a reasonable tradeoff even if it reduces our
69
+ # at-a-glance perception of how things work.
70
70
  #
71
71
  # class Todo
72
72
  # # Other todo implementation
@@ -99,7 +99,7 @@ class Module
99
99
  # end
100
100
  #
101
101
  # Todo.ancestors
102
- # # => Todo, Todo::EventTracking, Object
102
+ # # => [Todo, Todo::EventTracking, Object]
103
103
  #
104
104
  # This small step has some wonderful ripple effects. We can
105
105
  # * grok the behavior of our class in one glance,
@@ -5,10 +5,11 @@ class Module
5
5
  # option is not used.
6
6
  class DelegationError < NoMethodError; end
7
7
 
8
- RUBY_RESERVED_WORDS = Set.new(
9
- %w(alias and BEGIN begin break case class def defined? do else elsif END
10
- end ensure false for if in module next nil not or redo rescue retry
11
- return self super then true undef unless until when while yield)
8
+ DELEGATION_RESERVED_METHOD_NAMES = Set.new(
9
+ %w(_ arg args alias and BEGIN begin block break case class def defined? do
10
+ else elsif END end ensure false for if in module next nil not or redo
11
+ rescue retry return self super then true undef unless until when while
12
+ yield)
12
13
  ).freeze
13
14
 
14
15
  # Provides a +delegate+ class method to easily expose contained objects'
@@ -17,7 +18,7 @@ class Module
17
18
  # ==== Options
18
19
  # * <tt>:to</tt> - Specifies the target object
19
20
  # * <tt>:prefix</tt> - Prefixes the new method with the target name or a custom prefix
20
- # * <tt>:allow_nil</tt> - if set to true, prevents a +NoMethodError+ to be raised
21
+ # * <tt>:allow_nil</tt> - if set to true, prevents a +NoMethodError+ from being raised
21
22
  #
22
23
  # The macro receives one or more method names (specified as symbols or
23
24
  # strings) and the name of the target object via the <tt>:to</tt> option
@@ -148,14 +149,11 @@ class Module
148
149
  #
149
150
  # The target method must be public, otherwise it will raise +NoMethodError+.
150
151
  #
151
- def delegate(*methods)
152
- options = methods.pop
153
- unless options.is_a?(Hash) && to = options[:to]
152
+ def delegate(*methods, to: nil, prefix: nil, allow_nil: nil)
153
+ unless to
154
154
  raise ArgumentError, 'Delegation needs a target. Supply an options hash with a :to key as the last argument (e.g. delegate :hello, to: :greeter).'
155
155
  end
156
156
 
157
- prefix, allow_nil = options.values_at(:prefix, :allow_nil)
158
-
159
157
  if prefix == true && to =~ /^[^a-z_]/
160
158
  raise ArgumentError, 'Can only automatically set the delegation prefix when delegating to a method.'
161
159
  end
@@ -167,11 +165,11 @@ class Module
167
165
  ''
168
166
  end
169
167
 
170
- file, line = caller.first.split(':', 2)
171
- line = line.to_i
168
+ location = caller_locations(1, 1).first
169
+ file, line = location.path, location.lineno
172
170
 
173
171
  to = to.to_s
174
- to = "self.#{to}" if RUBY_RESERVED_WORDS.include?(to)
172
+ to = "self.#{to}" if DELEGATION_RESERVED_METHOD_NAMES.include?(to)
175
173
 
176
174
  methods.each do |method|
177
175
  # Attribute writer methods only accept one argument. Makes sure []=
@@ -185,19 +183,31 @@ class Module
185
183
  # On the other hand it could be that the target has side-effects,
186
184
  # whereas conceptually, from the user point of view, the delegator should
187
185
  # be doing one call.
188
-
189
- exception = %(raise DelegationError, "#{self}##{method_prefix}#{method} delegated to #{to}.#{method}, but #{to} is nil: \#{self.inspect}")
190
-
191
- method_def = [
192
- "def #{method_prefix}#{method}(#{definition})",
193
- " _ = #{to}",
194
- " if !_.nil? || nil.respond_to?(:#{method})",
195
- " _.#{method}(#{definition})",
196
- " else",
197
- " #{exception unless allow_nil}",
198
- " end",
186
+ if allow_nil
187
+ method_def = [
188
+ "def #{method_prefix}#{method}(#{definition})",
189
+ "_ = #{to}",
190
+ "if !_.nil? || nil.respond_to?(:#{method})",
191
+ " _.#{method}(#{definition})",
192
+ "end",
199
193
  "end"
200
- ].join ';'
194
+ ].join ';'
195
+ else
196
+ exception = %(raise DelegationError, "#{self}##{method_prefix}#{method} delegated to #{to}.#{method}, but #{to} is nil: \#{self.inspect}")
197
+
198
+ method_def = [
199
+ "def #{method_prefix}#{method}(#{definition})",
200
+ " _ = #{to}",
201
+ " _.#{method}(#{definition})",
202
+ "rescue NoMethodError => e",
203
+ " if _.nil? && e.name == :#{method}",
204
+ " #{exception}",
205
+ " else",
206
+ " raise",
207
+ " end",
208
+ "end"
209
+ ].join ';'
210
+ end
201
211
 
202
212
  module_eval(method_def, file, line)
203
213
  end
@@ -13,8 +13,8 @@ class Module
13
13
  #
14
14
  # class MyLib::Deprecator
15
15
  # def deprecation_warning(deprecated_method_name, message, caller_backtrace = nil)
16
- # message = "#{deprecated_method_name} is deprecated and will be removed from MyLibrary | #{message}"
17
- # Kernel.warn message
16
+ # message = "#{deprecated_method_name} is deprecated and will be removed from MyLibrary | #{message}"
17
+ # Kernel.warn message
18
18
  # end
19
19
  # end
20
20
  def deprecate(*method_names)
@@ -57,6 +57,10 @@ class Module
57
57
  end
58
58
 
59
59
  def local_constants #:nodoc:
60
+ ActiveSupport::Deprecation.warn(<<-MSG.squish)
61
+ Module#local_constants is deprecated and will be removed in Rails 5.1.
62
+ Use Module#constants(false) instead.
63
+ MSG
60
64
  constants(false)
61
65
  end
62
66
  end
@@ -1,11 +1,3 @@
1
- class Module
2
- ###
3
- # TODO: remove this after 1.9 support is dropped
4
- def methods_transplantable? # :nodoc:
5
- x = Module.new { def foo; end }
6
- Module.new { define_method :bar, x.instance_method(:foo) }
7
- true
8
- rescue TypeError
9
- false
10
- end
11
- end
1
+ require 'active_support/deprecation'
2
+
3
+ ActiveSupport::Deprecation.warn("This file is deprecated and will be removed in Rails 5.1 with no replacement.")
@@ -3,13 +3,16 @@ require 'active_support/core_ext/string/inflections'
3
3
  #--
4
4
  # Allows code reuse in the methods below without polluting Module.
5
5
  #++
6
- module QualifiedConstUtils
7
- def self.raise_if_absolute(path)
8
- raise NameError.new("wrong constant name #$&") if path =~ /\A::[^:]+/
9
- end
10
6
 
11
- def self.names(path)
12
- path.split('::')
7
+ module ActiveSupport
8
+ module QualifiedConstUtils
9
+ def self.raise_if_absolute(path)
10
+ raise NameError.new("wrong constant name #$&") if path =~ /\A::[^:]+/
11
+ end
12
+
13
+ def self.names(path)
14
+ path.split('::')
15
+ end
13
16
  end
14
17
  end
15
18
 
@@ -24,9 +27,14 @@ end
24
27
  #++
25
28
  class Module
26
29
  def qualified_const_defined?(path, search_parents=true)
27
- QualifiedConstUtils.raise_if_absolute(path)
30
+ ActiveSupport::Deprecation.warn(<<-MESSAGE.squish)
31
+ Module#qualified_const_defined? is deprecated in favour of the builtin
32
+ Module#const_defined? and will be removed in Rails 5.1.
33
+ MESSAGE
28
34
 
29
- QualifiedConstUtils.names(path).inject(self) do |mod, name|
35
+ ActiveSupport::QualifiedConstUtils.raise_if_absolute(path)
36
+
37
+ ActiveSupport::QualifiedConstUtils.names(path).inject(self) do |mod, name|
30
38
  return unless mod.const_defined?(name, search_parents)
31
39
  mod.const_get(name)
32
40
  end
@@ -34,19 +42,29 @@ class Module
34
42
  end
35
43
 
36
44
  def qualified_const_get(path)
37
- QualifiedConstUtils.raise_if_absolute(path)
45
+ ActiveSupport::Deprecation.warn(<<-MESSAGE.squish)
46
+ Module#qualified_const_get is deprecated in favour of the builtin
47
+ Module#const_get and will be removed in Rails 5.1.
48
+ MESSAGE
49
+
50
+ ActiveSupport::QualifiedConstUtils.raise_if_absolute(path)
38
51
 
39
- QualifiedConstUtils.names(path).inject(self) do |mod, name|
52
+ ActiveSupport::QualifiedConstUtils.names(path).inject(self) do |mod, name|
40
53
  mod.const_get(name)
41
54
  end
42
55
  end
43
56
 
44
57
  def qualified_const_set(path, value)
45
- QualifiedConstUtils.raise_if_absolute(path)
58
+ ActiveSupport::Deprecation.warn(<<-MESSAGE.squish)
59
+ Module#qualified_const_set is deprecated in favour of the builtin
60
+ Module#const_set and will be removed in Rails 5.1.
61
+ MESSAGE
62
+
63
+ ActiveSupport::QualifiedConstUtils.raise_if_absolute(path)
46
64
 
47
65
  const_name = path.demodulize
48
66
  mod_name = path.deconstantize
49
- mod = mod_name.empty? ? self : qualified_const_get(mod_name)
67
+ mod = mod_name.empty? ? self : const_get(mod_name)
50
68
  mod.const_set(const_name, value)
51
69
  end
52
70
  end
@@ -1,12 +1,35 @@
1
1
  class Module
2
+ # Removes the named method, if it exists.
2
3
  def remove_possible_method(method)
3
4
  if method_defined?(method) || private_method_defined?(method)
4
5
  undef_method(method)
5
6
  end
6
7
  end
7
8
 
9
+ # Removes the named singleton method, if it exists.
10
+ def remove_possible_singleton_method(method)
11
+ singleton_class.instance_eval do
12
+ remove_possible_method(method)
13
+ end
14
+ end
15
+
16
+ # Replaces the existing method definition, if there is one, with the passed
17
+ # block as its body.
8
18
  def redefine_method(method, &block)
19
+ visibility = method_visibility(method)
9
20
  remove_possible_method(method)
10
21
  define_method(method, &block)
22
+ send(visibility, method)
23
+ end
24
+
25
+ def method_visibility(method) # :nodoc:
26
+ case
27
+ when private_method_defined?(method)
28
+ :private
29
+ when protected_method_defined?(method)
30
+ :protected
31
+ else
32
+ :public
33
+ end
11
34
  end
12
35
  end
@@ -3,6 +3,7 @@ require 'active_support/core_ext/module/introspection'
3
3
  require 'active_support/core_ext/module/anonymous'
4
4
  require 'active_support/core_ext/module/reachable'
5
5
  require 'active_support/core_ext/module/attribute_accessors'
6
+ require 'active_support/core_ext/module/attribute_accessors_per_thread'
6
7
  require 'active_support/core_ext/module/attr_internal'
7
8
  require 'active_support/core_ext/module/concerning'
8
9
  require 'active_support/core_ext/module/delegation'
@@ -1,5 +1,12 @@
1
1
  class NameError
2
2
  # Extract the name of the missing constant from the exception message.
3
+ #
4
+ # begin
5
+ # HelloWorld
6
+ # rescue NameError => e
7
+ # e.missing_name
8
+ # end
9
+ # # => "HelloWorld"
3
10
  def missing_name
4
11
  if /undefined local variable or method/ !~ message
5
12
  $1 if /((::)?([A-Z]\w*)(::[A-Z]\w*)*)$/ =~ message
@@ -7,10 +14,16 @@ class NameError
7
14
  end
8
15
 
9
16
  # Was this exception raised because the given name was missing?
17
+ #
18
+ # begin
19
+ # HelloWorld
20
+ # rescue NameError => e
21
+ # e.missing_name?("HelloWorld")
22
+ # end
23
+ # # => true
10
24
  def missing_name?(name)
11
25
  if name.is_a? Symbol
12
- last_name = (missing_name || '').split('::').last
13
- last_name == name.to_s
26
+ self.name == name
14
27
  else
15
28
  missing_name == name.to_s
16
29
  end
@@ -7,36 +7,56 @@ class Numeric
7
7
  EXABYTE = PETABYTE * 1024
8
8
 
9
9
  # Enables the use of byte calculations and declarations, like 45.bytes + 2.6.megabytes
10
+ #
11
+ # 2.bytes # => 2
10
12
  def bytes
11
13
  self
12
14
  end
13
15
  alias :byte :bytes
14
16
 
17
+ # Returns the number of bytes equivalent to the kilobytes provided.
18
+ #
19
+ # 2.kilobytes # => 2048
15
20
  def kilobytes
16
21
  self * KILOBYTE
17
22
  end
18
23
  alias :kilobyte :kilobytes
19
24
 
25
+ # Returns the number of bytes equivalent to the megabytes provided.
26
+ #
27
+ # 2.megabytes # => 2_097_152
20
28
  def megabytes
21
29
  self * MEGABYTE
22
30
  end
23
31
  alias :megabyte :megabytes
24
32
 
33
+ # Returns the number of bytes equivalent to the gigabytes provided.
34
+ #
35
+ # 2.gigabytes # => 2_147_483_648
25
36
  def gigabytes
26
37
  self * GIGABYTE
27
38
  end
28
39
  alias :gigabyte :gigabytes
29
40
 
41
+ # Returns the number of bytes equivalent to the terabytes provided.
42
+ #
43
+ # 2.terabytes # => 2_199_023_255_552
30
44
  def terabytes
31
45
  self * TERABYTE
32
46
  end
33
47
  alias :terabyte :terabytes
34
48
 
49
+ # Returns the number of bytes equivalent to the petabytes provided.
50
+ #
51
+ # 2.petabytes # => 2_251_799_813_685_248
35
52
  def petabytes
36
53
  self * PETABYTE
37
54
  end
38
55
  alias :petabyte :petabytes
39
56
 
57
+ # Returns the number of bytes equivalent to the exabytes provided.
58
+ #
59
+ # 2.exabytes # => 2_305_843_009_213_693_952
40
60
  def exabytes
41
61
  self * EXABYTE
42
62
  end
@@ -1,7 +1,8 @@
1
1
  require 'active_support/core_ext/big_decimal/conversions'
2
2
  require 'active_support/number_helper'
3
+ require 'active_support/core_ext/module/deprecation'
3
4
 
4
- class Numeric
5
+ module ActiveSupport::NumericWithFormat
5
6
 
6
7
  # Provides options for converting numbers into formatted strings.
7
8
  # Options are provided for phone numbers, currency, percentage,
@@ -14,71 +15,73 @@ class Numeric
14
15
  # ==== Examples
15
16
  #
16
17
  # Phone Numbers:
17
- # 5551234.to_s(:phone) # => 555-1234
18
- # 1235551234.to_s(:phone) # => 123-555-1234
19
- # 1235551234.to_s(:phone, area_code: true) # => (123) 555-1234
20
- # 1235551234.to_s(:phone, delimiter: ' ') # => 123 555 1234
21
- # 1235551234.to_s(:phone, area_code: true, extension: 555) # => (123) 555-1234 x 555
22
- # 1235551234.to_s(:phone, country_code: 1) # => +1-123-555-1234
18
+ # 5551234.to_s(:phone) # => "555-1234"
19
+ # 1235551234.to_s(:phone) # => "123-555-1234"
20
+ # 1235551234.to_s(:phone, area_code: true) # => "(123) 555-1234"
21
+ # 1235551234.to_s(:phone, delimiter: ' ') # => "123 555 1234"
22
+ # 1235551234.to_s(:phone, area_code: true, extension: 555) # => "(123) 555-1234 x 555"
23
+ # 1235551234.to_s(:phone, country_code: 1) # => "+1-123-555-1234"
23
24
  # 1235551234.to_s(:phone, country_code: 1, extension: 1343, delimiter: '.')
24
- # # => +1.123.555.1234 x 1343
25
+ # # => "+1.123.555.1234 x 1343"
25
26
  #
26
27
  # Currency:
27
- # 1234567890.50.to_s(:currency) # => $1,234,567,890.50
28
- # 1234567890.506.to_s(:currency) # => $1,234,567,890.51
29
- # 1234567890.506.to_s(:currency, precision: 3) # => $1,234,567,890.506
30
- # 1234567890.506.to_s(:currency, locale: :fr) # => 1 234 567 890,51 €
28
+ # 1234567890.50.to_s(:currency) # => "$1,234,567,890.50"
29
+ # 1234567890.506.to_s(:currency) # => "$1,234,567,890.51"
30
+ # 1234567890.506.to_s(:currency, precision: 3) # => "$1,234,567,890.506"
31
+ # 1234567890.506.to_s(:currency, locale: :fr) # => "1 234 567 890,51 €"
31
32
  # -1234567890.50.to_s(:currency, negative_format: '(%u%n)')
32
- # # => ($1,234,567,890.50)
33
+ # # => "($1,234,567,890.50)"
33
34
  # 1234567890.50.to_s(:currency, unit: '&pound;', separator: ',', delimiter: '')
34
- # # => &pound;1234567890,50
35
+ # # => "&pound;1234567890,50"
35
36
  # 1234567890.50.to_s(:currency, unit: '&pound;', separator: ',', delimiter: '', format: '%n %u')
36
- # # => 1234567890,50 &pound;
37
+ # # => "1234567890,50 &pound;"
37
38
  #
38
39
  # Percentage:
39
- # 100.to_s(:percentage) # => 100.000%
40
- # 100.to_s(:percentage, precision: 0) # => 100%
41
- # 1000.to_s(:percentage, delimiter: '.', separator: ',') # => 1.000,000%
42
- # 302.24398923423.to_s(:percentage, precision: 5) # => 302.24399%
43
- # 1000.to_s(:percentage, locale: :fr) # => 1 000,000%
44
- # 100.to_s(:percentage, format: '%n %') # => 100 %
40
+ # 100.to_s(:percentage) # => "100.000%"
41
+ # 100.to_s(:percentage, precision: 0) # => "100%"
42
+ # 1000.to_s(:percentage, delimiter: '.', separator: ',') # => "1.000,000%"
43
+ # 302.24398923423.to_s(:percentage, precision: 5) # => "302.24399%"
44
+ # 1000.to_s(:percentage, locale: :fr) # => "1 000,000%"
45
+ # 100.to_s(:percentage, format: '%n %') # => "100.000 %"
45
46
  #
46
47
  # Delimited:
47
- # 12345678.to_s(:delimited) # => 12,345,678
48
- # 12345678.05.to_s(:delimited) # => 12,345,678.05
49
- # 12345678.to_s(:delimited, delimiter: '.') # => 12.345.678
50
- # 12345678.to_s(:delimited, delimiter: ',') # => 12,345,678
51
- # 12345678.05.to_s(:delimited, separator: ' ') # => 12,345,678 05
52
- # 12345678.05.to_s(:delimited, locale: :fr) # => 12 345 678,05
48
+ # 12345678.to_s(:delimited) # => "12,345,678"
49
+ # 12345678.05.to_s(:delimited) # => "12,345,678.05"
50
+ # 12345678.to_s(:delimited, delimiter: '.') # => "12.345.678"
51
+ # 12345678.to_s(:delimited, delimiter: ',') # => "12,345,678"
52
+ # 12345678.05.to_s(:delimited, separator: ' ') # => "12,345,678 05"
53
+ # 12345678.05.to_s(:delimited, locale: :fr) # => "12 345 678,05"
53
54
  # 98765432.98.to_s(:delimited, delimiter: ' ', separator: ',')
54
- # # => 98 765 432,98
55
+ # # => "98 765 432,98"
55
56
  #
56
57
  # Rounded:
57
- # 111.2345.to_s(:rounded) # => 111.235
58
- # 111.2345.to_s(:rounded, precision: 2) # => 111.23
59
- # 13.to_s(:rounded, precision: 5) # => 13.00000
60
- # 389.32314.to_s(:rounded, precision: 0) # => 389
61
- # 111.2345.to_s(:rounded, significant: true) # => 111
62
- # 111.2345.to_s(:rounded, precision: 1, significant: true) # => 100
63
- # 13.to_s(:rounded, precision: 5, significant: true) # => 13.000
64
- # 111.234.to_s(:rounded, locale: :fr) # => 111,234
58
+ # 111.2345.to_s(:rounded) # => "111.235"
59
+ # 111.2345.to_s(:rounded, precision: 2) # => "111.23"
60
+ # 13.to_s(:rounded, precision: 5) # => "13.00000"
61
+ # 389.32314.to_s(:rounded, precision: 0) # => "389"
62
+ # 111.2345.to_s(:rounded, significant: true) # => "111"
63
+ # 111.2345.to_s(:rounded, precision: 1, significant: true) # => "100"
64
+ # 13.to_s(:rounded, precision: 5, significant: true) # => "13.000"
65
+ # 111.234.to_s(:rounded, locale: :fr) # => "111,234"
65
66
  # 13.to_s(:rounded, precision: 5, significant: true, strip_insignificant_zeros: true)
66
- # # => 13
67
- # 389.32314.to_s(:rounded, precision: 4, significant: true) # => 389.3
67
+ # # => "13"
68
+ # 389.32314.to_s(:rounded, precision: 4, significant: true) # => "389.3"
68
69
  # 1111.2345.to_s(:rounded, precision: 2, separator: ',', delimiter: '.')
69
- # # => 1.111,23
70
+ # # => "1.111,23"
70
71
  #
71
72
  # Human-friendly size in Bytes:
72
- # 123.to_s(:human_size) # => 123 Bytes
73
- # 1234.to_s(:human_size) # => 1.21 KB
74
- # 12345.to_s(:human_size) # => 12.1 KB
75
- # 1234567.to_s(:human_size) # => 1.18 MB
76
- # 1234567890.to_s(:human_size) # => 1.15 GB
77
- # 1234567890123.to_s(:human_size) # => 1.12 TB
78
- # 1234567.to_s(:human_size, precision: 2) # => 1.2 MB
79
- # 483989.to_s(:human_size, precision: 2) # => 470 KB
80
- # 1234567.to_s(:human_size, precision: 2, separator: ',') # => 1,2 MB
81
- # 1234567890123.to_s(:human_size, precision: 5) # => "1.1229 TB"
73
+ # 123.to_s(:human_size) # => "123 Bytes"
74
+ # 1234.to_s(:human_size) # => "1.21 KB"
75
+ # 12345.to_s(:human_size) # => "12.1 KB"
76
+ # 1234567.to_s(:human_size) # => "1.18 MB"
77
+ # 1234567890.to_s(:human_size) # => "1.15 GB"
78
+ # 1234567890123.to_s(:human_size) # => "1.12 TB"
79
+ # 1234567890123456.to_s(:human_size) # => "1.1 PB"
80
+ # 1234567890123456789.to_s(:human_size) # => "1.07 EB"
81
+ # 1234567.to_s(:human_size, precision: 2) # => "1.2 MB"
82
+ # 483989.to_s(:human_size, precision: 2) # => "470 KB"
83
+ # 1234567.to_s(:human_size, precision: 2, separator: ',') # => "1,2 MB"
84
+ # 1234567890123.to_s(:human_size, precision: 5) # => "1.1228 TB"
82
85
  # 524288000.to_s(:human_size, precision: 5) # => "500 MB"
83
86
  #
84
87
  # Human-friendly format:
@@ -97,7 +100,10 @@ class Numeric
97
100
  # 1234567.to_s(:human, precision: 1,
98
101
  # separator: ',',
99
102
  # significant: false) # => "1,2 Million"
100
- def to_formatted_s(format = :default, options = {})
103
+ def to_s(*args)
104
+ format, options = args
105
+ options ||= {}
106
+
101
107
  case format
102
108
  when :phone
103
109
  return ActiveSupport::NumberHelper.number_to_phone(self, options)
@@ -114,22 +120,26 @@ class Numeric
114
120
  when :human_size
115
121
  return ActiveSupport::NumberHelper.number_to_human_size(self, options)
116
122
  else
117
- self.to_default_s
118
- end
119
- end
120
-
121
- [Float, Fixnum, Bignum, BigDecimal].each do |klass|
122
- klass.send(:alias_method, :to_default_s, :to_s)
123
-
124
- klass.send(:define_method, :to_s) do |*args|
125
- if args[0].is_a?(Symbol)
126
- format = args[0]
127
- options = args[1] || {}
128
-
129
- self.to_formatted_s(format, options)
123
+ if is_a?(Float) || format.is_a?(Symbol)
124
+ super()
130
125
  else
131
- to_default_s(*args)
126
+ super
132
127
  end
133
128
  end
134
129
  end
130
+
131
+ def to_formatted_s(*args)
132
+ to_s(*args)
133
+ end
134
+ deprecate to_formatted_s: :to_s
135
+ end
136
+
137
+ # Ruby 2.4+ unifies Fixnum & Bignum into Integer.
138
+ if Integer == Fixnum
139
+ Integer.prepend ActiveSupport::NumericWithFormat
140
+ else
141
+ Fixnum.prepend ActiveSupport::NumericWithFormat
142
+ Bignum.prepend ActiveSupport::NumericWithFormat
135
143
  end
144
+ Float.prepend ActiveSupport::NumericWithFormat
145
+ BigDecimal.prepend ActiveSupport::NumericWithFormat
@@ -0,0 +1,26 @@
1
+ unless 1.respond_to?(:positive?) # TODO: Remove this file when we drop support to ruby < 2.3
2
+ class Numeric
3
+ # Returns true if the number is positive.
4
+ #
5
+ # 1.positive? # => true
6
+ # 0.positive? # => false
7
+ # -1.positive? # => false
8
+ def positive?
9
+ self > 0
10
+ end
11
+
12
+ # Returns true if the number is negative.
13
+ #
14
+ # -1.negative? # => true
15
+ # 0.negative? # => false
16
+ # 1.negative? # => false
17
+ def negative?
18
+ self < 0
19
+ end
20
+ end
21
+
22
+ class Complex
23
+ undef :positive?
24
+ undef :negative?
25
+ end
26
+ end