activesupport 5.2.4.3 → 7.0.3

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 (228) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +244 -459
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +4 -3
  5. data/lib/active_support/actionable_error.rb +48 -0
  6. data/lib/active_support/array_inquirer.rb +2 -2
  7. data/lib/active_support/backtrace_cleaner.rb +31 -5
  8. data/lib/active_support/benchmarkable.rb +3 -3
  9. data/lib/active_support/cache/file_store.rb +47 -41
  10. data/lib/active_support/cache/mem_cache_store.rb +151 -40
  11. data/lib/active_support/cache/memory_store.rb +68 -34
  12. data/lib/active_support/cache/null_store.rb +16 -3
  13. data/lib/active_support/cache/redis_cache_store.rb +103 -101
  14. data/lib/active_support/cache/strategy/local_cache.rb +56 -64
  15. data/lib/active_support/cache.rb +333 -116
  16. data/lib/active_support/callbacks.rb +244 -128
  17. data/lib/active_support/code_generator.rb +65 -0
  18. data/lib/active_support/concern.rb +72 -5
  19. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +16 -0
  20. data/lib/active_support/concurrency/share_lock.rb +2 -3
  21. data/lib/active_support/configurable.rb +15 -16
  22. data/lib/active_support/configuration_file.rb +51 -0
  23. data/lib/active_support/core_ext/array/access.rb +15 -7
  24. data/lib/active_support/core_ext/array/conversions.rb +18 -17
  25. data/lib/active_support/core_ext/array/deprecated_conversions.rb +25 -0
  26. data/lib/active_support/core_ext/array/extract.rb +21 -0
  27. data/lib/active_support/core_ext/array/grouping.rb +6 -6
  28. data/lib/active_support/core_ext/array/inquiry.rb +2 -2
  29. data/lib/active_support/core_ext/array.rb +2 -1
  30. data/lib/active_support/core_ext/benchmark.rb +2 -2
  31. data/lib/active_support/core_ext/big_decimal/conversions.rb +1 -1
  32. data/lib/active_support/core_ext/class/attribute.rb +32 -47
  33. data/lib/active_support/core_ext/class/subclasses.rb +9 -22
  34. data/lib/active_support/core_ext/date/blank.rb +1 -1
  35. data/lib/active_support/core_ext/date/calculations.rb +15 -14
  36. data/lib/active_support/core_ext/date/conversions.rb +16 -15
  37. data/lib/active_support/core_ext/date/deprecated_conversions.rb +26 -0
  38. data/lib/active_support/core_ext/date.rb +1 -0
  39. data/lib/active_support/core_ext/date_and_time/calculations.rb +41 -51
  40. data/lib/active_support/core_ext/date_and_time/compatibility.rb +15 -0
  41. data/lib/active_support/core_ext/date_and_time/zones.rb +0 -1
  42. data/lib/active_support/core_ext/date_time/blank.rb +1 -1
  43. data/lib/active_support/core_ext/date_time/calculations.rb +1 -1
  44. data/lib/active_support/core_ext/date_time/conversions.rb +13 -14
  45. data/lib/active_support/core_ext/date_time/deprecated_conversions.rb +22 -0
  46. data/lib/active_support/core_ext/date_time.rb +1 -0
  47. data/lib/active_support/core_ext/digest/uuid.rb +39 -13
  48. data/lib/active_support/core_ext/enumerable.rb +241 -76
  49. data/lib/active_support/core_ext/file/atomic.rb +3 -1
  50. data/lib/active_support/core_ext/hash/conversions.rb +3 -4
  51. data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
  52. data/lib/active_support/core_ext/hash/except.rb +2 -2
  53. data/lib/active_support/core_ext/hash/indifferent_access.rb +3 -3
  54. data/lib/active_support/core_ext/hash/keys.rb +2 -31
  55. data/lib/active_support/core_ext/hash/slice.rb +6 -27
  56. data/lib/active_support/core_ext/hash.rb +1 -2
  57. data/lib/active_support/core_ext/integer/multiple.rb +1 -1
  58. data/lib/active_support/core_ext/kernel/reporting.rb +4 -4
  59. data/lib/active_support/core_ext/kernel/singleton_class.rb +1 -1
  60. data/lib/active_support/core_ext/kernel.rb +0 -1
  61. data/lib/active_support/core_ext/load_error.rb +1 -1
  62. data/lib/active_support/core_ext/module/attr_internal.rb +2 -2
  63. data/lib/active_support/core_ext/module/attribute_accessors.rb +32 -39
  64. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +35 -28
  65. data/lib/active_support/core_ext/module/concerning.rb +8 -2
  66. data/lib/active_support/core_ext/module/delegation.rb +70 -33
  67. data/lib/active_support/core_ext/module/introspection.rb +16 -15
  68. data/lib/active_support/core_ext/module/redefine_method.rb +8 -17
  69. data/lib/active_support/core_ext/module.rb +0 -1
  70. data/lib/active_support/core_ext/name_error.rb +23 -2
  71. data/lib/active_support/core_ext/numeric/conversions.rb +132 -129
  72. data/lib/active_support/core_ext/numeric/deprecated_conversions.rb +60 -0
  73. data/lib/active_support/core_ext/numeric.rb +1 -1
  74. data/lib/active_support/core_ext/object/acts_like.rb +29 -5
  75. data/lib/active_support/core_ext/object/blank.rb +3 -4
  76. data/lib/active_support/core_ext/object/deep_dup.rb +1 -1
  77. data/lib/active_support/core_ext/object/duplicable.rb +14 -110
  78. data/lib/active_support/core_ext/object/json.rb +44 -27
  79. data/lib/active_support/core_ext/object/to_query.rb +2 -2
  80. data/lib/active_support/core_ext/object/try.rb +24 -14
  81. data/lib/active_support/core_ext/object/with_options.rb +21 -2
  82. data/lib/active_support/core_ext/pathname/existence.rb +21 -0
  83. data/lib/active_support/core_ext/pathname.rb +3 -0
  84. data/lib/active_support/core_ext/range/compare_range.rb +23 -27
  85. data/lib/active_support/core_ext/range/conversions.rb +32 -30
  86. data/lib/active_support/core_ext/range/deprecated_conversions.rb +26 -0
  87. data/lib/active_support/core_ext/range/each.rb +1 -2
  88. data/lib/active_support/core_ext/range/include_time_with_zone.rb +4 -20
  89. data/lib/active_support/core_ext/range/overlaps.rb +1 -1
  90. data/lib/active_support/core_ext/range.rb +1 -1
  91. data/lib/active_support/core_ext/regexp.rb +8 -5
  92. data/lib/active_support/core_ext/securerandom.rb +23 -3
  93. data/lib/active_support/core_ext/string/access.rb +5 -16
  94. data/lib/active_support/core_ext/string/conversions.rb +3 -2
  95. data/lib/active_support/core_ext/string/filters.rb +42 -1
  96. data/lib/active_support/core_ext/string/inflections.rb +46 -7
  97. data/lib/active_support/core_ext/string/inquiry.rb +2 -1
  98. data/lib/active_support/core_ext/string/multibyte.rb +6 -5
  99. data/lib/active_support/core_ext/string/output_safety.rb +129 -20
  100. data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -2
  101. data/lib/active_support/core_ext/string/strip.rb +3 -1
  102. data/lib/active_support/core_ext/symbol/starts_ends_with.rb +6 -0
  103. data/lib/active_support/core_ext/symbol.rb +3 -0
  104. data/lib/active_support/core_ext/time/calculations.rb +59 -10
  105. data/lib/active_support/core_ext/time/conversions.rb +15 -12
  106. data/lib/active_support/core_ext/time/deprecated_conversions.rb +22 -0
  107. data/lib/active_support/core_ext/time/zones.rb +7 -22
  108. data/lib/active_support/core_ext/time.rb +1 -0
  109. data/lib/active_support/core_ext/uri.rb +3 -22
  110. data/lib/active_support/core_ext.rb +2 -1
  111. data/lib/active_support/current_attributes/test_helper.rb +13 -0
  112. data/lib/active_support/current_attributes.rb +47 -16
  113. data/lib/active_support/dependencies/interlock.rb +10 -18
  114. data/lib/active_support/dependencies/require_dependency.rb +28 -0
  115. data/lib/active_support/dependencies.rb +60 -715
  116. data/lib/active_support/deprecation/behaviors.rb +21 -5
  117. data/lib/active_support/deprecation/disallowed.rb +56 -0
  118. data/lib/active_support/deprecation/instance_delegator.rb +0 -1
  119. data/lib/active_support/deprecation/method_wrappers.rb +18 -23
  120. data/lib/active_support/deprecation/proxy_wrappers.rb +31 -8
  121. data/lib/active_support/deprecation/reporting.rb +50 -7
  122. data/lib/active_support/deprecation.rb +7 -2
  123. data/lib/active_support/descendants_tracker.rb +190 -34
  124. data/lib/active_support/digest.rb +5 -3
  125. data/lib/active_support/duration/iso8601_parser.rb +5 -7
  126. data/lib/active_support/duration/iso8601_serializer.rb +27 -15
  127. data/lib/active_support/duration.rb +149 -67
  128. data/lib/active_support/encrypted_configuration.rb +12 -5
  129. data/lib/active_support/encrypted_file.rb +23 -5
  130. data/lib/active_support/environment_inquirer.rb +20 -0
  131. data/lib/active_support/error_reporter.rb +117 -0
  132. data/lib/active_support/evented_file_update_checker.rb +85 -122
  133. data/lib/active_support/execution_context/test_helper.rb +13 -0
  134. data/lib/active_support/execution_context.rb +53 -0
  135. data/lib/active_support/execution_wrapper.rb +44 -21
  136. data/lib/active_support/executor/test_helper.rb +7 -0
  137. data/lib/active_support/file_update_checker.rb +0 -1
  138. data/lib/active_support/fork_tracker.rb +71 -0
  139. data/lib/active_support/gem_version.rb +5 -5
  140. data/lib/active_support/hash_with_indifferent_access.rb +73 -43
  141. data/lib/active_support/html_safe_translation.rb +43 -0
  142. data/lib/active_support/i18n.rb +2 -0
  143. data/lib/active_support/i18n_railtie.rb +15 -8
  144. data/lib/active_support/inflector/inflections.rb +25 -14
  145. data/lib/active_support/inflector/methods.rb +38 -71
  146. data/lib/active_support/inflector/transliterate.rb +47 -18
  147. data/lib/active_support/isolated_execution_state.rb +72 -0
  148. data/lib/active_support/json/decoding.rb +25 -26
  149. data/lib/active_support/json/encoding.rb +14 -6
  150. data/lib/active_support/key_generator.rb +23 -38
  151. data/lib/active_support/lazy_load_hooks.rb +19 -5
  152. data/lib/active_support/locale/en.rb +33 -0
  153. data/lib/active_support/locale/en.yml +8 -4
  154. data/lib/active_support/log_subscriber/test_helper.rb +2 -2
  155. data/lib/active_support/log_subscriber.rb +51 -11
  156. data/lib/active_support/logger.rb +6 -22
  157. data/lib/active_support/logger_silence.rb +11 -19
  158. data/lib/active_support/logger_thread_safe_level.rb +45 -10
  159. data/lib/active_support/message_encryptor.rb +20 -19
  160. data/lib/active_support/message_verifier.rb +53 -21
  161. data/lib/active_support/messages/metadata.rb +13 -4
  162. data/lib/active_support/messages/rotation_configuration.rb +2 -1
  163. data/lib/active_support/messages/rotator.rb +10 -9
  164. data/lib/active_support/multibyte/chars.rb +17 -76
  165. data/lib/active_support/multibyte/unicode.rb +7 -331
  166. data/lib/active_support/multibyte.rb +1 -1
  167. data/lib/active_support/notifications/fanout.rb +163 -37
  168. data/lib/active_support/notifications/instrumenter.rb +90 -11
  169. data/lib/active_support/notifications.rb +88 -30
  170. data/lib/active_support/number_helper/number_converter.rb +6 -9
  171. data/lib/active_support/number_helper/number_to_currency_converter.rb +12 -12
  172. data/lib/active_support/number_helper/number_to_delimited_converter.rb +4 -3
  173. data/lib/active_support/number_helper/number_to_human_converter.rb +4 -3
  174. data/lib/active_support/number_helper/number_to_human_size_converter.rb +5 -4
  175. data/lib/active_support/number_helper/number_to_percentage_converter.rb +3 -1
  176. data/lib/active_support/number_helper/number_to_phone_converter.rb +3 -2
  177. data/lib/active_support/number_helper/number_to_rounded_converter.rb +12 -7
  178. data/lib/active_support/number_helper/rounding_helper.rb +12 -32
  179. data/lib/active_support/number_helper.rb +36 -12
  180. data/lib/active_support/option_merger.rb +15 -4
  181. data/lib/active_support/ordered_hash.rb +2 -2
  182. data/lib/active_support/ordered_options.rb +14 -4
  183. data/lib/active_support/parameter_filter.rb +138 -0
  184. data/lib/active_support/per_thread_registry.rb +6 -1
  185. data/lib/active_support/rails.rb +1 -10
  186. data/lib/active_support/railtie.rb +77 -5
  187. data/lib/active_support/reloader.rb +5 -6
  188. data/lib/active_support/rescuable.rb +8 -8
  189. data/lib/active_support/ruby_features.rb +7 -0
  190. data/lib/active_support/secure_compare_rotator.rb +51 -0
  191. data/lib/active_support/security_utils.rb +19 -12
  192. data/lib/active_support/string_inquirer.rb +2 -3
  193. data/lib/active_support/subscriber.rb +79 -46
  194. data/lib/active_support/tagged_logging.rb +58 -9
  195. data/lib/active_support/test_case.rb +79 -0
  196. data/lib/active_support/testing/assertions.rb +62 -11
  197. data/lib/active_support/testing/deprecation.rb +52 -2
  198. data/lib/active_support/testing/file_fixtures.rb +2 -0
  199. data/lib/active_support/testing/isolation.rb +4 -4
  200. data/lib/active_support/testing/method_call_assertions.rb +32 -5
  201. data/lib/active_support/testing/parallelization/server.rb +82 -0
  202. data/lib/active_support/testing/parallelization/worker.rb +103 -0
  203. data/lib/active_support/testing/parallelization.rb +55 -0
  204. data/lib/active_support/testing/parallelize_executor.rb +76 -0
  205. data/lib/active_support/testing/stream.rb +4 -7
  206. data/lib/active_support/testing/tagged_logging.rb +1 -1
  207. data/lib/active_support/testing/time_helpers.rb +60 -14
  208. data/lib/active_support/time_with_zone.rb +139 -64
  209. data/lib/active_support/values/time_zone.rb +66 -30
  210. data/lib/active_support/version.rb +1 -1
  211. data/lib/active_support/xml_mini/jdom.rb +3 -4
  212. data/lib/active_support/xml_mini/libxml.rb +7 -7
  213. data/lib/active_support/xml_mini/libxmlsax.rb +5 -5
  214. data/lib/active_support/xml_mini/nokogiri.rb +6 -6
  215. data/lib/active_support/xml_mini/nokogirisax.rb +4 -4
  216. data/lib/active_support/xml_mini/rexml.rb +11 -4
  217. data/lib/active_support/xml_mini.rb +7 -14
  218. data/lib/active_support.rb +30 -1
  219. metadata +64 -35
  220. data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -9
  221. data/lib/active_support/core_ext/hash/compact.rb +0 -29
  222. data/lib/active_support/core_ext/hash/transform_values.rb +0 -32
  223. data/lib/active_support/core_ext/kernel/agnostics.rb +0 -13
  224. data/lib/active_support/core_ext/marshal.rb +0 -24
  225. data/lib/active_support/core_ext/module/reachable.rb +0 -11
  226. data/lib/active_support/core_ext/numeric/inquiry.rb +0 -28
  227. data/lib/active_support/core_ext/range/include_range.rb +0 -3
  228. data/lib/active_support/values/unicode_tables.dat +0 -0
@@ -28,93 +28,6 @@ class Object
28
28
  end
29
29
  end
30
30
 
31
- class NilClass
32
- begin
33
- nil.dup
34
- rescue TypeError
35
-
36
- # +nil+ is not duplicable:
37
- #
38
- # nil.duplicable? # => false
39
- # nil.dup # => TypeError: can't dup NilClass
40
- def duplicable?
41
- false
42
- end
43
- end
44
- end
45
-
46
- class FalseClass
47
- begin
48
- false.dup
49
- rescue TypeError
50
-
51
- # +false+ is not duplicable:
52
- #
53
- # false.duplicable? # => false
54
- # false.dup # => TypeError: can't dup FalseClass
55
- def duplicable?
56
- false
57
- end
58
- end
59
- end
60
-
61
- class TrueClass
62
- begin
63
- true.dup
64
- rescue TypeError
65
-
66
- # +true+ is not duplicable:
67
- #
68
- # true.duplicable? # => false
69
- # true.dup # => TypeError: can't dup TrueClass
70
- def duplicable?
71
- false
72
- end
73
- end
74
- end
75
-
76
- class Symbol
77
- begin
78
- :symbol.dup # Ruby 2.4.x.
79
- "symbol_from_string".to_sym.dup # Some symbols can't `dup` in Ruby 2.4.0.
80
- rescue TypeError
81
-
82
- # Symbols are not duplicable:
83
- #
84
- # :my_symbol.duplicable? # => false
85
- # :my_symbol.dup # => TypeError: can't dup Symbol
86
- def duplicable?
87
- false
88
- end
89
- end
90
- end
91
-
92
- class Numeric
93
- begin
94
- 1.dup
95
- rescue TypeError
96
-
97
- # Numbers are not duplicable:
98
- #
99
- # 3.duplicable? # => false
100
- # 3.dup # => TypeError: can't dup Integer
101
- def duplicable?
102
- false
103
- end
104
- end
105
- end
106
-
107
- require "bigdecimal"
108
- class BigDecimal
109
- # BigDecimals are duplicable:
110
- #
111
- # BigDecimal("1.2").duplicable? # => true
112
- # BigDecimal("1.2").dup # => #<BigDecimal:...,'0.12E1',18(18)>
113
- def duplicable?
114
- true
115
- end
116
- end
117
-
118
31
  class Method
119
32
  # Methods are not duplicable:
120
33
  #
@@ -125,32 +38,23 @@ class Method
125
38
  end
126
39
  end
127
40
 
128
- class Complex
129
- begin
130
- Complex(1).dup
131
- rescue TypeError
132
-
133
- # Complexes are not duplicable:
134
- #
135
- # Complex(1).duplicable? # => false
136
- # Complex(1).dup # => TypeError: can't copy Complex
137
- def duplicable?
138
- false
139
- end
41
+ class UnboundMethod
42
+ # Unbound methods are not duplicable:
43
+ #
44
+ # method(:puts).unbind.duplicable? # => false
45
+ # method(:puts).unbind.dup # => TypeError: allocator undefined for UnboundMethod
46
+ def duplicable?
47
+ false
140
48
  end
141
49
  end
142
50
 
143
- class Rational
144
- begin
145
- Rational(1).dup
146
- rescue TypeError
51
+ require "singleton"
147
52
 
148
- # Rationals are not duplicable:
149
- #
150
- # Rational(1).duplicable? # => false
151
- # Rational(1).dup # => TypeError: can't copy Rational
152
- def duplicable?
153
- false
154
- end
53
+ module Singleton
54
+ # Singleton instances are not duplicable:
55
+ #
56
+ # Class.new.include(Singleton).instance.dup # TypeError (can't dup instance of singleton
57
+ def duplicable?
58
+ false
155
59
  end
156
60
  end
@@ -1,8 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Hack to load json gem first so we can overwrite its to_json.
3
+ # Hack to load json gem first so we can override its to_json.
4
4
  require "json"
5
5
  require "bigdecimal"
6
+ require "ipaddr"
6
7
  require "uri/generic"
7
8
  require "pathname"
8
9
  require "active_support/core_ext/big_decimal/conversions" # for #to_s
@@ -14,11 +15,11 @@ require "active_support/core_ext/time/conversions"
14
15
  require "active_support/core_ext/date_time/conversions"
15
16
  require "active_support/core_ext/date/conversions"
16
17
 
18
+ #--
17
19
  # The JSON gem adds a few modules to Ruby core classes containing :to_json definition, overwriting
18
20
  # their default behavior. That said, we need to define the basic to_json method in all of them,
19
21
  # otherwise they will always use to_json gem implementation, which is backwards incompatible in
20
- # several cases (for instance, the JSON implementation for Hash does not work) with inheritance
21
- # and consequently classes as ActiveSupport::OrderedHash cannot be serialized to json.
22
+ # several cases (for instance, the JSON implementation for Hash does not work) with inheritance.
22
23
  #
23
24
  # On the other hand, we should avoid conflict with ::JSON.{generate,dump}(obj). Unfortunately, the
24
25
  # JSON gem's encoder relies on its own to_json implementation to encode objects. Since it always
@@ -44,12 +45,18 @@ module ActiveSupport
44
45
  end
45
46
  end
46
47
 
47
- [Object, Array, FalseClass, Float, Hash, Integer, NilClass, String, TrueClass, Enumerable].reverse_each do |klass|
48
+ [Enumerable, Object, Array, FalseClass, Float, Hash, Integer, NilClass, String, TrueClass].reverse_each do |klass|
48
49
  klass.prepend(ActiveSupport::ToJsonWithActiveSupportEncoder)
49
50
  end
50
51
 
52
+ class Module
53
+ def as_json(options = nil) # :nodoc:
54
+ name
55
+ end
56
+ end
57
+
51
58
  class Object
52
- def as_json(options = nil) #:nodoc:
59
+ def as_json(options = nil) # :nodoc:
53
60
  if respond_to?(:to_hash)
54
61
  to_hash.as_json(options)
55
62
  else
@@ -58,44 +65,44 @@ class Object
58
65
  end
59
66
  end
60
67
 
61
- class Struct #:nodoc:
68
+ class Struct # :nodoc:
62
69
  def as_json(options = nil)
63
70
  Hash[members.zip(values)].as_json(options)
64
71
  end
65
72
  end
66
73
 
67
74
  class TrueClass
68
- def as_json(options = nil) #:nodoc:
75
+ def as_json(options = nil) # :nodoc:
69
76
  self
70
77
  end
71
78
  end
72
79
 
73
80
  class FalseClass
74
- def as_json(options = nil) #:nodoc:
81
+ def as_json(options = nil) # :nodoc:
75
82
  self
76
83
  end
77
84
  end
78
85
 
79
86
  class NilClass
80
- def as_json(options = nil) #:nodoc:
87
+ def as_json(options = nil) # :nodoc:
81
88
  self
82
89
  end
83
90
  end
84
91
 
85
92
  class String
86
- def as_json(options = nil) #:nodoc:
93
+ def as_json(options = nil) # :nodoc:
87
94
  self
88
95
  end
89
96
  end
90
97
 
91
98
  class Symbol
92
- def as_json(options = nil) #:nodoc:
99
+ def as_json(options = nil) # :nodoc:
93
100
  to_s
94
101
  end
95
102
  end
96
103
 
97
104
  class Numeric
98
- def as_json(options = nil) #:nodoc:
105
+ def as_json(options = nil) # :nodoc:
99
106
  self
100
107
  end
101
108
  end
@@ -103,7 +110,7 @@ end
103
110
  class Float
104
111
  # Encoding Infinity or NaN to JSON should return "null". The default returns
105
112
  # "Infinity" or "NaN" which are not valid JSON.
106
- def as_json(options = nil) #:nodoc:
113
+ def as_json(options = nil) # :nodoc:
107
114
  finite? ? self : nil
108
115
  end
109
116
  end
@@ -118,43 +125,43 @@ class BigDecimal
118
125
  # if the other end knows by contract that the data is supposed to be a
119
126
  # BigDecimal, it still has the chance to post-process the string and get the
120
127
  # real value.
121
- def as_json(options = nil) #:nodoc:
128
+ def as_json(options = nil) # :nodoc:
122
129
  finite? ? to_s : nil
123
130
  end
124
131
  end
125
132
 
126
133
  class Regexp
127
- def as_json(options = nil) #:nodoc:
134
+ def as_json(options = nil) # :nodoc:
128
135
  to_s
129
136
  end
130
137
  end
131
138
 
132
139
  module Enumerable
133
- def as_json(options = nil) #:nodoc:
140
+ def as_json(options = nil) # :nodoc:
134
141
  to_a.as_json(options)
135
142
  end
136
143
  end
137
144
 
138
145
  class IO
139
- def as_json(options = nil) #:nodoc:
146
+ def as_json(options = nil) # :nodoc:
140
147
  to_s
141
148
  end
142
149
  end
143
150
 
144
151
  class Range
145
- def as_json(options = nil) #:nodoc:
152
+ def as_json(options = nil) # :nodoc:
146
153
  to_s
147
154
  end
148
155
  end
149
156
 
150
157
  class Array
151
- def as_json(options = nil) #:nodoc:
158
+ def as_json(options = nil) # :nodoc:
152
159
  map { |v| options ? v.as_json(options.dup) : v.as_json }
153
160
  end
154
161
  end
155
162
 
156
163
  class Hash
157
- def as_json(options = nil) #:nodoc:
164
+ def as_json(options = nil) # :nodoc:
158
165
  # create a subset of the hash by applying :only or :except
159
166
  subset = if options
160
167
  if attrs = options[:only]
@@ -168,12 +175,16 @@ class Hash
168
175
  self
169
176
  end
170
177
 
171
- Hash[subset.map { |k, v| [k.to_s, options ? v.as_json(options.dup) : v.as_json] }]
178
+ result = {}
179
+ subset.each do |k, v|
180
+ result[k.to_s] = options ? v.as_json(options.dup) : v.as_json
181
+ end
182
+ result
172
183
  end
173
184
  end
174
185
 
175
186
  class Time
176
- def as_json(options = nil) #:nodoc:
187
+ def as_json(options = nil) # :nodoc:
177
188
  if ActiveSupport::JSON::Encoding.use_standard_json_time_format
178
189
  xmlschema(ActiveSupport::JSON::Encoding.time_precision)
179
190
  else
@@ -183,7 +194,7 @@ class Time
183
194
  end
184
195
 
185
196
  class Date
186
- def as_json(options = nil) #:nodoc:
197
+ def as_json(options = nil) # :nodoc:
187
198
  if ActiveSupport::JSON::Encoding.use_standard_json_time_format
188
199
  strftime("%Y-%m-%d")
189
200
  else
@@ -193,7 +204,7 @@ class Date
193
204
  end
194
205
 
195
206
  class DateTime
196
- def as_json(options = nil) #:nodoc:
207
+ def as_json(options = nil) # :nodoc:
197
208
  if ActiveSupport::JSON::Encoding.use_standard_json_time_format
198
209
  xmlschema(ActiveSupport::JSON::Encoding.time_precision)
199
210
  else
@@ -202,19 +213,25 @@ class DateTime
202
213
  end
203
214
  end
204
215
 
205
- class URI::Generic #:nodoc:
216
+ class URI::Generic # :nodoc:
217
+ def as_json(options = nil)
218
+ to_s
219
+ end
220
+ end
221
+
222
+ class Pathname # :nodoc:
206
223
  def as_json(options = nil)
207
224
  to_s
208
225
  end
209
226
  end
210
227
 
211
- class Pathname #:nodoc:
228
+ class IPAddr # :nodoc:
212
229
  def as_json(options = nil)
213
230
  to_s
214
231
  end
215
232
  end
216
233
 
217
- class Process::Status #:nodoc:
234
+ class Process::Status # :nodoc:
218
235
  def as_json(options = nil)
219
236
  { exitstatus: exitstatus, pid: pid }
220
237
  end
@@ -75,11 +75,11 @@ class Hash
75
75
  #
76
76
  # This method is also aliased as +to_param+.
77
77
  def to_query(namespace = nil)
78
- query = collect do |key, value|
78
+ query = filter_map do |key, value|
79
79
  unless (value.is_a?(Hash) || value.is_a?(Array)) && value.empty?
80
80
  value.to_query(namespace ? "#{namespace}[#{key}]" : key)
81
81
  end
82
- end.compact
82
+ end
83
83
 
84
84
  query.sort! unless namespace.to_s.include?("[]")
85
85
  query.join("&")
@@ -3,22 +3,32 @@
3
3
  require "delegate"
4
4
 
5
5
  module ActiveSupport
6
- module Tryable #:nodoc:
7
- def try(*a, &b)
8
- try!(*a, &b) if a.empty? || respond_to?(a.first)
6
+ module Tryable # :nodoc:
7
+ def try(*args, &block)
8
+ if args.empty? && block_given?
9
+ if block.arity == 0
10
+ instance_eval(&block)
11
+ else
12
+ yield self
13
+ end
14
+ elsif respond_to?(args.first)
15
+ public_send(*args, &block)
16
+ end
9
17
  end
18
+ ruby2_keywords(:try)
10
19
 
11
- def try!(*a, &b)
12
- if a.empty? && block_given?
13
- if b.arity == 0
14
- instance_eval(&b)
20
+ def try!(*args, &block)
21
+ if args.empty? && block_given?
22
+ if block.arity == 0
23
+ instance_eval(&block)
15
24
  else
16
25
  yield self
17
26
  end
18
27
  else
19
- public_send(*a, &b)
28
+ public_send(*args, &block)
20
29
  end
21
30
  end
31
+ ruby2_keywords(:try!)
22
32
  end
23
33
  end
24
34
 
@@ -29,7 +39,7 @@ class Object
29
39
  # :method: try
30
40
  #
31
41
  # :call-seq:
32
- # try(*a, &b)
42
+ # try(*args, &block)
33
43
  #
34
44
  # Invokes the public method whose name goes as first argument just like
35
45
  # +public_send+ does, except that if the receiver does not respond to it the
@@ -94,7 +104,7 @@ class Object
94
104
  # :method: try!
95
105
  #
96
106
  # :call-seq:
97
- # try!(*a, &b)
107
+ # try!(*args, &block)
98
108
  #
99
109
  # Same as #try, but raises a +NoMethodError+ exception if the receiver is
100
110
  # not +nil+ and does not implement the tried method.
@@ -111,7 +121,7 @@ class Delegator
111
121
  # :method: try
112
122
  #
113
123
  # :call-seq:
114
- # try(a*, &b)
124
+ # try(*args, &block)
115
125
  #
116
126
  # See Object#try
117
127
 
@@ -119,7 +129,7 @@ class Delegator
119
129
  # :method: try!
120
130
  #
121
131
  # :call-seq:
122
- # try!(a*, &b)
132
+ # try!(*args, &block)
123
133
  #
124
134
  # See Object#try!
125
135
  end
@@ -135,14 +145,14 @@ class NilClass
135
145
  #
136
146
  # With +try+
137
147
  # @person.try(:children).try(:first).try(:name)
138
- def try(*args)
148
+ def try(*)
139
149
  nil
140
150
  end
141
151
 
142
152
  # Calling +try!+ on +nil+ always returns +nil+.
143
153
  #
144
154
  # nil.try!(:name) # => nil
145
- def try!(*args)
155
+ def try!(*)
146
156
  nil
147
157
  end
148
158
  end
@@ -68,15 +68,34 @@ class Object
68
68
  # You can access these methods using the class name instead:
69
69
  #
70
70
  # class Phone < ActiveRecord::Base
71
- # enum phone_number_type: [home: 0, office: 1, mobile: 2]
71
+ # enum phone_number_type: { home: 0, office: 1, mobile: 2 }
72
72
  #
73
73
  # with_options presence: true do
74
74
  # validates :phone_number_type, inclusion: { in: Phone.phone_number_types.keys }
75
75
  # end
76
76
  # end
77
77
  #
78
+ # When the block argument is omitted, the decorated Object instance is returned:
79
+ #
80
+ # module MyStyledHelpers
81
+ # def styled
82
+ # with_options style: "color: red;"
83
+ # end
84
+ # end
85
+ #
86
+ # # styled.link_to "I'm red", "/"
87
+ # # #=> <a href="/" style="color: red;">I'm red</a>
88
+ #
89
+ # # styled.button_tag "I'm red too!"
90
+ # # #=> <button style="color: red;">I'm red too!</button>
91
+ #
78
92
  def with_options(options, &block)
79
93
  option_merger = ActiveSupport::OptionMerger.new(self, options)
80
- block.arity.zero? ? option_merger.instance_eval(&block) : block.call(option_merger)
94
+
95
+ if block
96
+ block.arity.zero? ? option_merger.instance_eval(&block) : block.call(option_merger)
97
+ else
98
+ option_merger
99
+ end
81
100
  end
82
101
  end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Pathname
4
+ # Returns the receiver if the named file exists otherwise returns +nil+.
5
+ # <tt>pathname.existence</tt> is equivalent to
6
+ #
7
+ # pathname.exist? ? pathname : nil
8
+ #
9
+ # For example, something like
10
+ #
11
+ # content = pathname.read if pathname.exist?
12
+ #
13
+ # becomes
14
+ #
15
+ # content = pathname.existence&.read
16
+ #
17
+ # @return [Pathname]
18
+ def existence
19
+ self if exist?
20
+ end
21
+ end
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/pathname/existence"
@@ -1,56 +1,52 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveSupport
4
- module CompareWithRange #:nodoc:
4
+ module CompareWithRange
5
5
  # Extends the default Range#=== to support range comparisons.
6
- # (1..5) === (1..5) # => true
7
- # (1..5) === (2..3) # => true
8
- # (1..5) === (2..6) # => false
6
+ # (1..5) === (1..5) # => true
7
+ # (1..5) === (2..3) # => true
8
+ # (1..5) === (1...6) # => true
9
+ # (1..5) === (2..6) # => false
9
10
  #
10
11
  # The native Range#=== behavior is untouched.
11
12
  # ('a'..'f') === ('c') # => true
12
13
  # (5..9) === (11) # => false
14
+ #
15
+ # The given range must be fully bounded, with both start and end.
13
16
  def ===(value)
14
17
  if value.is_a?(::Range)
18
+ is_backwards_op = value.exclude_end? ? :>= : :>
19
+ return false if value.begin && value.end && value.begin.public_send(is_backwards_op, value.end)
15
20
  # 1...10 includes 1..9 but it does not include 1..10.
21
+ # 1..10 includes 1...11 but it does not include 1...12.
16
22
  operator = exclude_end? && !value.exclude_end? ? :< : :<=
17
- super(value.first) && value.last.send(operator, last)
23
+ value_max = !exclude_end? && value.exclude_end? ? value.max : value.last
24
+ super(value.first) && (self.end.nil? || value_max.public_send(operator, last))
18
25
  else
19
26
  super
20
27
  end
21
28
  end
22
29
 
23
30
  # Extends the default Range#include? to support range comparisons.
24
- # (1..5).include?(1..5) # => true
25
- # (1..5).include?(2..3) # => true
26
- # (1..5).include?(2..6) # => false
31
+ # (1..5).include?(1..5) # => true
32
+ # (1..5).include?(2..3) # => true
33
+ # (1..5).include?(1...6) # => true
34
+ # (1..5).include?(2..6) # => false
27
35
  #
28
36
  # The native Range#include? behavior is untouched.
29
37
  # ('a'..'f').include?('c') # => true
30
38
  # (5..9).include?(11) # => false
39
+ #
40
+ # The given range must be fully bounded, with both start and end.
31
41
  def include?(value)
32
42
  if value.is_a?(::Range)
43
+ is_backwards_op = value.exclude_end? ? :>= : :>
44
+ return false if value.begin && value.end && value.begin.public_send(is_backwards_op, value.end)
33
45
  # 1...10 includes 1..9 but it does not include 1..10.
46
+ # 1..10 includes 1...11 but it does not include 1...12.
34
47
  operator = exclude_end? && !value.exclude_end? ? :< : :<=
35
- super(value.first) && value.last.send(operator, last)
36
- else
37
- super
38
- end
39
- end
40
-
41
- # Extends the default Range#cover? to support range comparisons.
42
- # (1..5).cover?(1..5) # => true
43
- # (1..5).cover?(2..3) # => true
44
- # (1..5).cover?(2..6) # => false
45
- #
46
- # The native Range#cover? behavior is untouched.
47
- # ('a'..'f').cover?('c') # => true
48
- # (5..9).cover?(11) # => false
49
- def cover?(value)
50
- if value.is_a?(::Range)
51
- # 1...10 covers 1..9 but it does not cover 1..10.
52
- operator = exclude_end? && !value.exclude_end? ? :< : :<=
53
- super(value.first) && value.last.send(operator, last)
48
+ value_max = !exclude_end? && value.exclude_end? ? value.max : value.last
49
+ super(value.first) && (self.end.nil? || value_max.public_send(operator, last))
54
50
  else
55
51
  super
56
52
  end
@@ -1,39 +1,41 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module ActiveSupport::RangeWithFormat
4
- RANGE_FORMATS = {
5
- db: -> (start, stop) do
6
- case start
7
- when String then "BETWEEN '#{start}' AND '#{stop}'"
8
- else
9
- "BETWEEN '#{start.to_s(:db)}' AND '#{stop.to_s(:db)}'"
3
+ module ActiveSupport
4
+ module RangeWithFormat
5
+ RANGE_FORMATS = {
6
+ db: -> (start, stop) do
7
+ case start
8
+ when String then "BETWEEN '#{start}' AND '#{stop}'"
9
+ else
10
+ "BETWEEN '#{start.to_fs(:db)}' AND '#{stop.to_fs(:db)}'"
11
+ end
10
12
  end
11
- end
12
- }
13
+ }
13
14
 
14
- # Convert range to a formatted string. See RANGE_FORMATS for predefined formats.
15
- #
16
- # range = (1..100) # => 1..100
17
- #
18
- # range.to_s # => "1..100"
19
- # range.to_s(:db) # => "BETWEEN '1' AND '100'"
20
- #
21
- # == Adding your own range formats to to_s
22
- # You can add your own formats to the Range::RANGE_FORMATS hash.
23
- # Use the format name as the hash key and a Proc instance.
24
- #
25
- # # config/initializers/range_formats.rb
26
- # Range::RANGE_FORMATS[:short] = ->(start, stop) { "Between #{start.to_s(:db)} and #{stop.to_s(:db)}" }
27
- def to_s(format = :default)
28
- if formatter = RANGE_FORMATS[format]
29
- formatter.call(first, last)
30
- else
31
- super()
15
+ # Convert range to a formatted string. See RANGE_FORMATS for predefined formats.
16
+ #
17
+ # This method is aliased to <tt>to_formatted_s</tt>.
18
+ #
19
+ # range = (1..100) # => 1..100
20
+ #
21
+ # range.to_s # => "1..100"
22
+ # range.to_fs(:db) # => "BETWEEN '1' AND '100'"
23
+ #
24
+ # == Adding your own range formats to to_s
25
+ # You can add your own formats to the Range::RANGE_FORMATS hash.
26
+ # Use the format name as the hash key and a Proc instance.
27
+ #
28
+ # # config/initializers/range_formats.rb
29
+ # Range::RANGE_FORMATS[:short] = ->(start, stop) { "Between #{start.to_fs(:db)} and #{stop.to_fs(:db)}" }
30
+ def to_fs(format = :default)
31
+ if formatter = RANGE_FORMATS[format]
32
+ formatter.call(first, last)
33
+ else
34
+ to_s
35
+ end
32
36
  end
37
+ alias_method :to_formatted_s, :to_fs
33
38
  end
34
-
35
- alias_method :to_default_s, :to_s
36
- alias_method :to_formatted_s, :to_s
37
39
  end
38
40
 
39
41
  Range.prepend(ActiveSupport::RangeWithFormat)