activesupport 4.0.13 → 5.2.5

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 (264) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +412 -444
  3. data/MIT-LICENSE +2 -2
  4. data/README.rdoc +8 -4
  5. data/lib/active_support/all.rb +5 -3
  6. data/lib/active_support/array_inquirer.rb +48 -0
  7. data/lib/active_support/backtrace_cleaner.rb +14 -12
  8. data/lib/active_support/benchmarkable.rb +6 -14
  9. data/lib/active_support/builder.rb +3 -1
  10. data/lib/active_support/cache/file_store.rb +67 -51
  11. data/lib/active_support/cache/mem_cache_store.rb +95 -97
  12. data/lib/active_support/cache/memory_store.rb +28 -30
  13. data/lib/active_support/cache/null_store.rb +7 -8
  14. data/lib/active_support/cache/redis_cache_store.rb +466 -0
  15. data/lib/active_support/cache/strategy/local_cache.rb +70 -56
  16. data/lib/active_support/cache/strategy/local_cache_middleware.rb +45 -0
  17. data/lib/active_support/cache.rb +331 -206
  18. data/lib/active_support/callbacks.rb +697 -426
  19. data/lib/active_support/concern.rb +32 -10
  20. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +17 -0
  21. data/lib/active_support/concurrency/share_lock.rb +227 -0
  22. data/lib/active_support/configurable.rb +8 -5
  23. data/lib/active_support/core_ext/array/access.rb +39 -1
  24. data/lib/active_support/core_ext/array/conversions.rb +24 -35
  25. data/lib/active_support/core_ext/array/extract_options.rb +2 -0
  26. data/lib/active_support/core_ext/array/grouping.rb +23 -13
  27. data/lib/active_support/core_ext/array/inquiry.rb +19 -0
  28. data/lib/active_support/core_ext/array/prepend_and_append.rb +7 -5
  29. data/lib/active_support/core_ext/array/wrap.rb +7 -4
  30. data/lib/active_support/core_ext/array.rb +9 -7
  31. data/lib/active_support/core_ext/benchmark.rb +3 -1
  32. data/lib/active_support/core_ext/big_decimal/conversions.rb +9 -26
  33. data/lib/active_support/core_ext/big_decimal.rb +3 -1
  34. data/lib/active_support/core_ext/class/attribute.rb +41 -23
  35. data/lib/active_support/core_ext/class/attribute_accessors.rb +5 -169
  36. data/lib/active_support/core_ext/class/subclasses.rb +20 -8
  37. data/lib/active_support/core_ext/class.rb +4 -4
  38. data/lib/active_support/core_ext/date/acts_like.rb +3 -1
  39. data/lib/active_support/core_ext/date/blank.rb +14 -0
  40. data/lib/active_support/core_ext/date/calculations.rb +21 -9
  41. data/lib/active_support/core_ext/date/conversions.rb +32 -22
  42. data/lib/active_support/core_ext/date/zones.rb +5 -34
  43. data/lib/active_support/core_ext/date.rb +6 -4
  44. data/lib/active_support/core_ext/date_and_time/calculations.rb +199 -57
  45. data/lib/active_support/core_ext/date_and_time/compatibility.rb +16 -0
  46. data/lib/active_support/core_ext/date_and_time/zones.rb +41 -0
  47. data/lib/active_support/core_ext/date_time/acts_like.rb +4 -2
  48. data/lib/active_support/core_ext/date_time/blank.rb +14 -0
  49. data/lib/active_support/core_ext/date_time/calculations.rb +78 -37
  50. data/lib/active_support/core_ext/date_time/compatibility.rb +18 -0
  51. data/lib/active_support/core_ext/date_time/conversions.rb +19 -13
  52. data/lib/active_support/core_ext/date_time.rb +7 -4
  53. data/lib/active_support/core_ext/digest/uuid.rb +53 -0
  54. data/lib/active_support/core_ext/digest.rb +3 -0
  55. data/lib/active_support/core_ext/enumerable.rb +113 -29
  56. data/lib/active_support/core_ext/file/atomic.rb +38 -31
  57. data/lib/active_support/core_ext/file.rb +3 -1
  58. data/lib/active_support/core_ext/hash/compact.rb +29 -0
  59. data/lib/active_support/core_ext/hash/conversions.rb +71 -49
  60. data/lib/active_support/core_ext/hash/deep_merge.rb +9 -13
  61. data/lib/active_support/core_ext/hash/except.rb +12 -3
  62. data/lib/active_support/core_ext/hash/indifferent_access.rb +5 -3
  63. data/lib/active_support/core_ext/hash/keys.rb +50 -38
  64. data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
  65. data/lib/active_support/core_ext/hash/slice.rb +12 -6
  66. data/lib/active_support/core_ext/hash/transform_values.rb +32 -0
  67. data/lib/active_support/core_ext/hash.rb +11 -8
  68. data/lib/active_support/core_ext/integer/inflections.rb +3 -1
  69. data/lib/active_support/core_ext/integer/multiple.rb +2 -0
  70. data/lib/active_support/core_ext/integer/time.rb +11 -33
  71. data/lib/active_support/core_ext/integer.rb +5 -3
  72. data/lib/active_support/core_ext/kernel/agnostics.rb +2 -0
  73. data/lib/active_support/core_ext/kernel/concern.rb +14 -0
  74. data/lib/active_support/core_ext/kernel/reporting.rb +5 -74
  75. data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
  76. data/lib/active_support/core_ext/kernel.rb +6 -4
  77. data/lib/active_support/core_ext/load_error.rb +5 -21
  78. data/lib/active_support/core_ext/marshal.rb +13 -10
  79. data/lib/active_support/core_ext/module/aliasing.rb +6 -44
  80. data/lib/active_support/core_ext/module/anonymous.rb +12 -1
  81. data/lib/active_support/core_ext/module/attr_internal.rb +8 -8
  82. data/lib/active_support/core_ext/module/attribute_accessors.rb +170 -21
  83. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +150 -0
  84. data/lib/active_support/core_ext/module/concerning.rb +134 -0
  85. data/lib/active_support/core_ext/module/delegation.rb +135 -45
  86. data/lib/active_support/core_ext/module/deprecation.rb +3 -3
  87. data/lib/active_support/core_ext/module/introspection.rb +9 -25
  88. data/lib/active_support/core_ext/module/reachable.rb +5 -2
  89. data/lib/active_support/core_ext/module/redefine_method.rb +49 -0
  90. data/lib/active_support/core_ext/module/remove_method.rb +8 -3
  91. data/lib/active_support/core_ext/module.rb +14 -10
  92. data/lib/active_support/core_ext/name_error.rb +22 -2
  93. data/lib/active_support/core_ext/numeric/bytes.rb +22 -0
  94. data/lib/active_support/core_ext/numeric/conversions.rb +79 -74
  95. data/lib/active_support/core_ext/numeric/inquiry.rb +28 -0
  96. data/lib/active_support/core_ext/numeric/time.rb +37 -50
  97. data/lib/active_support/core_ext/numeric.rb +6 -3
  98. data/lib/active_support/core_ext/object/acts_like.rb +12 -1
  99. data/lib/active_support/core_ext/object/blank.rb +70 -19
  100. data/lib/active_support/core_ext/object/conversions.rb +6 -4
  101. data/lib/active_support/core_ext/object/deep_dup.rb +19 -10
  102. data/lib/active_support/core_ext/object/duplicable.rb +100 -34
  103. data/lib/active_support/core_ext/object/inclusion.rb +18 -15
  104. data/lib/active_support/core_ext/object/instance_variables.rb +3 -1
  105. data/lib/active_support/core_ext/object/json.rb +227 -0
  106. data/lib/active_support/core_ext/object/to_param.rb +3 -1
  107. data/lib/active_support/core_ext/object/to_query.rb +21 -8
  108. data/lib/active_support/core_ext/object/try.rb +94 -24
  109. data/lib/active_support/core_ext/object/with_options.rb +45 -5
  110. data/lib/active_support/core_ext/object.rb +14 -12
  111. data/lib/active_support/core_ext/range/compare_range.rb +61 -0
  112. data/lib/active_support/core_ext/range/conversions.rb +27 -7
  113. data/lib/active_support/core_ext/range/each.rb +19 -17
  114. data/lib/active_support/core_ext/range/include_range.rb +2 -22
  115. data/lib/active_support/core_ext/range/include_time_with_zone.rb +23 -0
  116. data/lib/active_support/core_ext/range/overlaps.rb +2 -0
  117. data/lib/active_support/core_ext/range.rb +7 -4
  118. data/lib/active_support/core_ext/regexp.rb +6 -0
  119. data/lib/active_support/core_ext/securerandom.rb +25 -0
  120. data/lib/active_support/core_ext/string/access.rb +41 -39
  121. data/lib/active_support/core_ext/string/behavior.rb +3 -1
  122. data/lib/active_support/core_ext/string/conversions.rb +17 -13
  123. data/lib/active_support/core_ext/string/exclude.rb +5 -3
  124. data/lib/active_support/core_ext/string/filters.rb +55 -6
  125. data/lib/active_support/core_ext/string/indent.rb +6 -4
  126. data/lib/active_support/core_ext/string/inflections.rb +66 -24
  127. data/lib/active_support/core_ext/string/inquiry.rb +3 -1
  128. data/lib/active_support/core_ext/string/multibyte.rb +15 -7
  129. data/lib/active_support/core_ext/string/output_safety.rb +114 -54
  130. data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -0
  131. data/lib/active_support/core_ext/string/strip.rb +4 -5
  132. data/lib/active_support/core_ext/string/zones.rb +4 -1
  133. data/lib/active_support/core_ext/string.rb +15 -13
  134. data/lib/active_support/core_ext/time/acts_like.rb +3 -1
  135. data/lib/active_support/core_ext/time/calculations.rb +123 -110
  136. data/lib/active_support/core_ext/time/compatibility.rb +16 -0
  137. data/lib/active_support/core_ext/time/conversions.rb +23 -14
  138. data/lib/active_support/core_ext/time/zones.rb +42 -26
  139. data/lib/active_support/core_ext/time.rb +7 -5
  140. data/lib/active_support/core_ext/uri.rb +6 -8
  141. data/lib/active_support/core_ext.rb +3 -2
  142. data/lib/active_support/current_attributes.rb +195 -0
  143. data/lib/active_support/dependencies/autoload.rb +3 -1
  144. data/lib/active_support/dependencies/interlock.rb +57 -0
  145. data/lib/active_support/dependencies.rb +196 -166
  146. data/lib/active_support/deprecation/behaviors.rb +48 -15
  147. data/lib/active_support/deprecation/constant_accessor.rb +52 -0
  148. data/lib/active_support/deprecation/instance_delegator.rb +17 -2
  149. data/lib/active_support/deprecation/method_wrappers.rb +66 -20
  150. data/lib/active_support/deprecation/proxy_wrappers.rb +56 -28
  151. data/lib/active_support/deprecation/reporting.rb +32 -12
  152. data/lib/active_support/deprecation.rb +14 -11
  153. data/lib/active_support/descendants_tracker.rb +2 -0
  154. data/lib/active_support/digest.rb +20 -0
  155. data/lib/active_support/duration/iso8601_parser.rb +125 -0
  156. data/lib/active_support/duration/iso8601_serializer.rb +55 -0
  157. data/lib/active_support/duration.rb +354 -34
  158. data/lib/active_support/encrypted_configuration.rb +49 -0
  159. data/lib/active_support/encrypted_file.rb +99 -0
  160. data/lib/active_support/evented_file_update_checker.rb +205 -0
  161. data/lib/active_support/execution_wrapper.rb +128 -0
  162. data/lib/active_support/executor.rb +8 -0
  163. data/lib/active_support/file_update_checker.rb +63 -37
  164. data/lib/active_support/gem_version.rb +17 -0
  165. data/lib/active_support/gzip.rb +7 -5
  166. data/lib/active_support/hash_with_indifferent_access.rb +158 -35
  167. data/lib/active_support/i18n.rb +8 -6
  168. data/lib/active_support/i18n_railtie.rb +38 -20
  169. data/lib/active_support/inflections.rb +19 -12
  170. data/lib/active_support/inflector/inflections.rb +79 -30
  171. data/lib/active_support/inflector/methods.rb +197 -129
  172. data/lib/active_support/inflector/transliterate.rb +48 -27
  173. data/lib/active_support/inflector.rb +7 -5
  174. data/lib/active_support/json/decoding.rb +21 -25
  175. data/lib/active_support/json/encoding.rb +84 -292
  176. data/lib/active_support/json.rb +4 -2
  177. data/lib/active_support/key_generator.rb +26 -28
  178. data/lib/active_support/lazy_load_hooks.rb +51 -21
  179. data/lib/active_support/locale/en.yml +2 -0
  180. data/lib/active_support/log_subscriber/test_helper.rb +14 -12
  181. data/lib/active_support/log_subscriber.rb +13 -10
  182. data/lib/active_support/logger.rb +54 -3
  183. data/lib/active_support/logger_silence.rb +12 -7
  184. data/lib/active_support/logger_thread_safe_level.rb +34 -0
  185. data/lib/active_support/message_encryptor.rb +173 -50
  186. data/lib/active_support/message_verifier.rb +159 -22
  187. data/lib/active_support/messages/metadata.rb +71 -0
  188. data/lib/active_support/messages/rotation_configuration.rb +22 -0
  189. data/lib/active_support/messages/rotator.rb +56 -0
  190. data/lib/active_support/multibyte/chars.rb +38 -26
  191. data/lib/active_support/multibyte/unicode.rb +138 -146
  192. data/lib/active_support/multibyte.rb +4 -2
  193. data/lib/active_support/notifications/fanout.rb +23 -16
  194. data/lib/active_support/notifications/instrumenter.rb +29 -8
  195. data/lib/active_support/notifications.rb +22 -13
  196. data/lib/active_support/number_helper/number_converter.rb +184 -0
  197. data/lib/active_support/number_helper/number_to_currency_converter.rb +46 -0
  198. data/lib/active_support/number_helper/number_to_delimited_converter.rb +29 -0
  199. data/lib/active_support/number_helper/number_to_human_converter.rb +68 -0
  200. data/lib/active_support/number_helper/number_to_human_size_converter.rb +59 -0
  201. data/lib/active_support/number_helper/number_to_percentage_converter.rb +14 -0
  202. data/lib/active_support/number_helper/number_to_phone_converter.rb +58 -0
  203. data/lib/active_support/number_helper/number_to_rounded_converter.rb +54 -0
  204. data/lib/active_support/number_helper/rounding_helper.rb +66 -0
  205. data/lib/active_support/number_helper.rb +125 -391
  206. data/lib/active_support/option_merger.rb +3 -1
  207. data/lib/active_support/ordered_hash.rb +6 -4
  208. data/lib/active_support/ordered_options.rb +31 -5
  209. data/lib/active_support/per_thread_registry.rb +19 -11
  210. data/lib/active_support/proxy_object.rb +2 -0
  211. data/lib/active_support/rails.rb +16 -8
  212. data/lib/active_support/railtie.rb +43 -9
  213. data/lib/active_support/reloader.rb +131 -0
  214. data/lib/active_support/rescuable.rb +108 -53
  215. data/lib/active_support/security_utils.rb +31 -0
  216. data/lib/active_support/string_inquirer.rb +11 -3
  217. data/lib/active_support/subscriber.rb +54 -17
  218. data/lib/active_support/tagged_logging.rb +14 -11
  219. data/lib/active_support/test_case.rb +42 -37
  220. data/lib/active_support/testing/assertions.rb +126 -39
  221. data/lib/active_support/testing/autorun.rb +5 -3
  222. data/lib/active_support/testing/constant_lookup.rb +3 -6
  223. data/lib/active_support/testing/declarative.rb +10 -22
  224. data/lib/active_support/testing/deprecation.rb +14 -10
  225. data/lib/active_support/testing/file_fixtures.rb +36 -0
  226. data/lib/active_support/testing/isolation.rb +55 -86
  227. data/lib/active_support/testing/method_call_assertions.rb +43 -0
  228. data/lib/active_support/testing/setup_and_teardown.rb +30 -10
  229. data/lib/active_support/testing/stream.rb +44 -0
  230. data/lib/active_support/testing/tagged_logging.rb +5 -3
  231. data/lib/active_support/testing/time_helpers.rb +200 -0
  232. data/lib/active_support/time.rb +13 -13
  233. data/lib/active_support/time_with_zone.rb +223 -73
  234. data/lib/active_support/values/time_zone.rb +261 -126
  235. data/lib/active_support/values/unicode_tables.dat +0 -0
  236. data/lib/active_support/version.rb +6 -7
  237. data/lib/active_support/xml_mini/jdom.rb +116 -113
  238. data/lib/active_support/xml_mini/libxml.rb +17 -16
  239. data/lib/active_support/xml_mini/libxmlsax.rb +16 -18
  240. data/lib/active_support/xml_mini/nokogiri.rb +15 -15
  241. data/lib/active_support/xml_mini/nokogirisax.rb +15 -16
  242. data/lib/active_support/xml_mini/rexml.rb +17 -16
  243. data/lib/active_support/xml_mini.rb +69 -51
  244. data/lib/active_support.rb +29 -3
  245. metadata +84 -54
  246. data/lib/active_support/basic_object.rb +0 -11
  247. data/lib/active_support/buffered_logger.rb +0 -21
  248. data/lib/active_support/concurrency/latch.rb +0 -27
  249. data/lib/active_support/core_ext/array/uniq_by.rb +0 -19
  250. data/lib/active_support/core_ext/class/delegating_attributes.rb +0 -40
  251. data/lib/active_support/core_ext/date_time/zones.rb +0 -24
  252. data/lib/active_support/core_ext/hash/diff.rb +0 -14
  253. data/lib/active_support/core_ext/kernel/debugger.rb +0 -10
  254. data/lib/active_support/core_ext/logger.rb +0 -67
  255. data/lib/active_support/core_ext/module/qualified_const.rb +0 -52
  256. data/lib/active_support/core_ext/object/to_json.rb +0 -27
  257. data/lib/active_support/core_ext/proc.rb +0 -17
  258. data/lib/active_support/core_ext/string/encoding.rb +0 -8
  259. data/lib/active_support/core_ext/struct.rb +0 -6
  260. data/lib/active_support/core_ext/thread.rb +0 -79
  261. data/lib/active_support/core_ext/time/marshal.rb +0 -30
  262. data/lib/active_support/file_watcher.rb +0 -36
  263. data/lib/active_support/json/variable.rb +0 -18
  264. data/lib/active_support/testing/pending.rb +0 -14
@@ -1,16 +1,18 @@
1
- require 'active_support/xml_mini'
2
- require 'active_support/time'
3
- require 'active_support/core_ext/object/blank'
4
- require 'active_support/core_ext/object/to_param'
5
- require 'active_support/core_ext/object/to_query'
6
- require 'active_support/core_ext/array/wrap'
7
- require 'active_support/core_ext/hash/reverse_merge'
8
- require 'active_support/core_ext/string/inflections'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/xml_mini"
4
+ require "active_support/time"
5
+ require "active_support/core_ext/object/blank"
6
+ require "active_support/core_ext/object/to_param"
7
+ require "active_support/core_ext/object/to_query"
8
+ require "active_support/core_ext/array/wrap"
9
+ require "active_support/core_ext/hash/reverse_merge"
10
+ require "active_support/core_ext/string/inflections"
9
11
 
10
12
  class Hash
11
13
  # Returns a string containing an XML representation of its receiver:
12
14
  #
13
- # {'foo' => 1, 'bar' => 2}.to_xml
15
+ # { foo: 1, bar: 2 }.to_xml
14
16
  # # =>
15
17
  # # <?xml version="1.0" encoding="UTF-8"?>
16
18
  # # <hash>
@@ -31,7 +33,7 @@ class Hash
31
33
  # with +key+ as <tt>:root</tt>, and +key+ singularized as second argument. The
32
34
  # callable can add nodes by using <tt>options[:builder]</tt>.
33
35
  #
34
- # 'foo'.to_xml(lambda { |options, key| options[:builder].b(key) })
36
+ # {foo: lambda { |options, key| options[:builder].b(key) }}.to_xml
35
37
  # # => "<b>foo</b>"
36
38
  #
37
39
  # * If +value+ responds to +to_xml+ the method is invoked with +key+ as <tt>:root</tt>.
@@ -43,7 +45,10 @@ class Hash
43
45
  # end
44
46
  #
45
47
  # { foo: Foo.new }.to_xml(skip_instruct: true)
46
- # # => "<hash><bar>fooing!</bar></hash>"
48
+ # # =>
49
+ # # <hash>
50
+ # # <bar>fooing!</bar>
51
+ # # </hash>
47
52
  #
48
53
  # * Otherwise, a node with +key+ as tag is created with a string representation of
49
54
  # +value+ as text node. If +value+ is +nil+ an attribute "nil" set to "true" is added.
@@ -52,8 +57,7 @@ class Hash
52
57
  #
53
58
  # XML_TYPE_NAMES = {
54
59
  # "Symbol" => "symbol",
55
- # "Fixnum" => "integer",
56
- # "Bignum" => "integer",
60
+ # "Integer" => "integer",
57
61
  # "BigDecimal" => "decimal",
58
62
  # "Float" => "float",
59
63
  # "TrueClass" => "boolean",
@@ -69,11 +73,11 @@ class Hash
69
73
  # configure your own builder with the <tt>:builder</tt> option. The method also accepts
70
74
  # options like <tt>:dasherize</tt> and friends, they are forwarded to the builder.
71
75
  def to_xml(options = {})
72
- require 'active_support/builder' unless defined?(Builder)
76
+ require "active_support/builder" unless defined?(Builder)
73
77
 
74
78
  options = options.dup
75
79
  options[:indent] ||= 2
76
- options[:root] ||= 'hash'
80
+ options[:root] ||= "hash"
77
81
  options[:builder] ||= Builder::XmlMarkup.new(indent: options[:indent])
78
82
 
79
83
  builder = options[:builder]
@@ -102,8 +106,26 @@ class Hash
102
106
  # hash = Hash.from_xml(xml)
103
107
  # # => {"hash"=>{"foo"=>1, "bar"=>2}}
104
108
  #
105
- # DisallowedType is raise if the XML contains attributes with <tt>type="yaml"</tt> or
106
- # <tt>type="symbol"</tt>. Use <tt>Hash.from_trusted_xml</tt> to parse this XML.
109
+ # +DisallowedType+ is raised if the XML contains attributes with <tt>type="yaml"</tt> or
110
+ # <tt>type="symbol"</tt>. Use <tt>Hash.from_trusted_xml</tt> to
111
+ # parse this XML.
112
+ #
113
+ # Custom +disallowed_types+ can also be passed in the form of an
114
+ # array.
115
+ #
116
+ # xml = <<-XML
117
+ # <?xml version="1.0" encoding="UTF-8"?>
118
+ # <hash>
119
+ # <foo type="integer">1</foo>
120
+ # <bar type="string">"David"</bar>
121
+ # </hash>
122
+ # XML
123
+ #
124
+ # hash = Hash.from_xml(xml, ['integer'])
125
+ # # => ActiveSupport::XMLConverter::DisallowedType: Disallowed type attribute: "integer"
126
+ #
127
+ # Note that passing custom disallowed types will override the default types,
128
+ # which are Symbol and YAML.
107
129
  def from_xml(xml, disallowed_types = nil)
108
130
  ActiveSupport::XMLConverter.new(xml, disallowed_types).to_h
109
131
  end
@@ -117,6 +139,8 @@ end
117
139
 
118
140
  module ActiveSupport
119
141
  class XMLConverter # :nodoc:
142
+ # Raised if the XML contains attributes with type="yaml" or
143
+ # type="symbol". Read Hash#from_xml for more details.
120
144
  class DisallowedType < StandardError
121
145
  def initialize(type)
122
146
  super "Disallowed type attribute: #{type.inspect}"
@@ -137,36 +161,36 @@ module ActiveSupport
137
161
  private
138
162
  def normalize_keys(params)
139
163
  case params
140
- when Hash
141
- Hash[params.map { |k,v| [k.to_s.tr('-', '_'), normalize_keys(v)] } ]
142
- when Array
143
- params.map { |v| normalize_keys(v) }
144
- else
145
- params
164
+ when Hash
165
+ Hash[params.map { |k, v| [k.to_s.tr("-", "_"), normalize_keys(v)] } ]
166
+ when Array
167
+ params.map { |v| normalize_keys(v) }
168
+ else
169
+ params
146
170
  end
147
171
  end
148
172
 
149
173
  def deep_to_h(value)
150
174
  case value
151
- when Hash
152
- process_hash(value)
153
- when Array
154
- process_array(value)
155
- when String
156
- value
157
- else
158
- raise "can't typecast #{value.class.name} - #{value.inspect}"
175
+ when Hash
176
+ process_hash(value)
177
+ when Array
178
+ process_array(value)
179
+ when String
180
+ value
181
+ else
182
+ raise "can't typecast #{value.class.name} - #{value.inspect}"
159
183
  end
160
184
  end
161
185
 
162
186
  def process_hash(value)
163
- if value.include?('type') && !value['type'].is_a?(Hash) && @disallowed_types.include?(value['type'])
164
- raise DisallowedType, value['type']
187
+ if value.include?("type") && !value["type"].is_a?(Hash) && @disallowed_types.include?(value["type"])
188
+ raise DisallowedType, value["type"]
165
189
  end
166
190
 
167
191
  if become_array?(value)
168
- _, entries = Array.wrap(value.detect { |k,v| not v.is_a?(String) })
169
- if entries.nil? || value['__content__'].try(:empty?)
192
+ _, entries = Array.wrap(value.detect { |k, v| not v.is_a?(String) })
193
+ if entries.nil? || value["__content__"].try(:empty?)
170
194
  []
171
195
  else
172
196
  case entries
@@ -182,28 +206,28 @@ module ActiveSupport
182
206
  process_content(value)
183
207
 
184
208
  elsif become_empty_string?(value)
185
- ''
209
+ ""
186
210
  elsif become_hash?(value)
187
- xml_value = Hash[value.map { |k,v| [k, deep_to_h(v)] }]
211
+ xml_value = Hash[value.map { |k, v| [k, deep_to_h(v)] }]
188
212
 
189
213
  # Turn { files: { file: #<StringIO> } } into { files: #<StringIO> } so it is compatible with
190
214
  # how multipart uploaded files from HTML appear
191
- xml_value['file'].is_a?(StringIO) ? xml_value['file'] : xml_value
215
+ xml_value["file"].is_a?(StringIO) ? xml_value["file"] : xml_value
192
216
  end
193
217
  end
194
218
 
195
219
  def become_content?(value)
196
- value['type'] == 'file' || (value['__content__'] && (value.keys.size == 1 || value['__content__'].present?))
220
+ value["type"] == "file" || (value["__content__"] && (value.keys.size == 1 || value["__content__"].present?))
197
221
  end
198
222
 
199
223
  def become_array?(value)
200
- value['type'] == 'array'
224
+ value["type"] == "array"
201
225
  end
202
226
 
203
227
  def become_empty_string?(value)
204
- # {"string" => true}
228
+ # { "string" => true }
205
229
  # No tests fail when the second term is removed.
206
- value['type'] == 'string' && value['nil'] != 'true'
230
+ value["type"] == "string" && value["nil"] != "true"
207
231
  end
208
232
 
209
233
  def become_hash?(value)
@@ -212,19 +236,19 @@ module ActiveSupport
212
236
 
213
237
  def nothing?(value)
214
238
  # blank or nil parsed values are represented by nil
215
- value.blank? || value['nil'] == 'true'
239
+ value.blank? || value["nil"] == "true"
216
240
  end
217
241
 
218
242
  def garbage?(value)
219
243
  # If the type is the only element which makes it then
220
244
  # this still makes the value nil, except if type is
221
- # a XML node(where type['value'] is a Hash)
222
- value['type'] && !value['type'].is_a?(::Hash) && value.size == 1
245
+ # an XML node(where type['value'] is a Hash)
246
+ value["type"] && !value["type"].is_a?(::Hash) && value.size == 1
223
247
  end
224
248
 
225
249
  def process_content(value)
226
- content = value['__content__']
227
- if parser = ActiveSupport::XmlMini::PARSING[value['type']]
250
+ content = value["__content__"]
251
+ if parser = ActiveSupport::XmlMini::PARSING[value["type"]]
228
252
  parser.arity == 1 ? parser.call(content) : parser.call(content, value)
229
253
  else
230
254
  content
@@ -235,7 +259,5 @@ module ActiveSupport
235
259
  value.map! { |i| deep_to_h(i) }
236
260
  value.length > 1 ? value : value.first
237
261
  end
238
-
239
262
  end
240
263
  end
241
-
@@ -1,10 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Hash
2
4
  # Returns a new hash with +self+ and +other_hash+ merged recursively.
3
5
  #
4
6
  # h1 = { a: true, b: { c: [1, 2, 3] } }
5
7
  # h2 = { a: false, b: { x: [3, 4, 5] } }
6
8
  #
7
- # h1.deep_merge(h2) #=> { a: false, b: { c: [1, 2, 3], x: [3, 4, 5] } }
9
+ # h1.deep_merge(h2) # => { a: false, b: { c: [1, 2, 3], x: [3, 4, 5] } }
8
10
  #
9
11
  # Like with Hash#merge in the standard library, a block can be provided
10
12
  # to merge values:
@@ -19,20 +21,14 @@ class Hash
19
21
 
20
22
  # Same as +deep_merge+, but modifies +self+.
21
23
  def deep_merge!(other_hash, &block)
22
- other_hash.each_pair do |current_key, other_value|
23
- this_value = self[current_key]
24
-
25
- self[current_key] = if this_value.is_a?(Hash) && other_value.is_a?(Hash)
26
- this_value.deep_merge(other_value, &block)
24
+ merge!(other_hash) do |key, this_val, other_val|
25
+ if this_val.is_a?(Hash) && other_val.is_a?(Hash)
26
+ this_val.deep_merge(other_val, &block)
27
+ elsif block_given?
28
+ block.call(key, this_val, other_val)
27
29
  else
28
- if block_given? && key?(current_key)
29
- block.call(current_key, this_value, other_value)
30
- else
31
- other_value
32
- end
30
+ other_val
33
31
  end
34
32
  end
35
-
36
- self
37
33
  end
38
34
  end
@@ -1,13 +1,22 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Hash
2
- # Return a hash that includes everything but the given keys. This is useful for
3
- # limiting a set of parameters to everything but a few known toggles:
4
+ # Returns a hash that includes everything except given keys.
5
+ # hash = { a: true, b: false, c: nil }
6
+ # hash.except(:c) # => { a: true, b: false }
7
+ # hash.except(:a, :b) # => { c: nil }
8
+ # hash # => { a: true, b: false, c: nil }
4
9
  #
10
+ # This is useful for limiting a set of parameters to everything but a few known toggles:
5
11
  # @person.update(params[:person].except(:admin))
6
12
  def except(*keys)
7
13
  dup.except!(*keys)
8
14
  end
9
15
 
10
- # Replaces the hash without the given keys.
16
+ # Removes the given keys from hash and returns it.
17
+ # hash = { a: true, b: false, c: nil }
18
+ # hash.except!(:c) # => { a: true, b: false }
19
+ # hash # => { a: true, b: false }
11
20
  def except!(*keys)
12
21
  keys.each { |key| delete(key) }
13
22
  self
@@ -1,12 +1,13 @@
1
- require 'active_support/hash_with_indifferent_access'
1
+ # frozen_string_literal: true
2
2
 
3
- class Hash
3
+ require "active_support/hash_with_indifferent_access"
4
4
 
5
+ class Hash
5
6
  # Returns an <tt>ActiveSupport::HashWithIndifferentAccess</tt> out of its receiver:
6
7
  #
7
8
  # { a: 1 }.with_indifferent_access['a'] # => 1
8
9
  def with_indifferent_access
9
- ActiveSupport::HashWithIndifferentAccess.new_from_hash_copying_default(self)
10
+ ActiveSupport::HashWithIndifferentAccess.new(self)
10
11
  end
11
12
 
12
13
  # Called when object is nested under an object that receives
@@ -18,5 +19,6 @@ class Hash
18
19
  #
19
20
  # b = { b: 1 }
20
21
  # { a: b }.with_indifferent_access['a'] # calls b.nested_under_indifferent_access
22
+ # # => {"b"=>1}
21
23
  alias nested_under_indifferent_access with_indifferent_access
22
24
  end
@@ -1,131 +1,143 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Hash
2
- # Return a new hash with all keys converted using the block operation.
4
+ # Returns a new hash with all keys converted using the +block+ operation.
3
5
  #
4
6
  # hash = { name: 'Rob', age: '28' }
5
7
  #
6
- # hash.transform_keys{ |key| key.to_s.upcase }
7
- # # => { "NAME" => "Rob", "AGE" => "28" }
8
+ # hash.transform_keys { |key| key.to_s.upcase } # => {"NAME"=>"Rob", "AGE"=>"28"}
9
+ #
10
+ # If you do not provide a +block+, it will return an Enumerator
11
+ # for chaining with other methods:
12
+ #
13
+ # hash.transform_keys.with_index { |k, i| [k, i].join } # => {"name0"=>"Rob", "age1"=>"28"}
8
14
  def transform_keys
15
+ return enum_for(:transform_keys) { size } unless block_given?
9
16
  result = {}
10
17
  each_key do |key|
11
18
  result[yield(key)] = self[key]
12
19
  end
13
20
  result
14
- end
21
+ end unless method_defined? :transform_keys
15
22
 
16
- # Destructively convert all keys using the block operations.
17
- # Same as transform_keys but modifies +self+.
23
+ # Destructively converts all keys using the +block+ operations.
24
+ # Same as +transform_keys+ but modifies +self+.
18
25
  def transform_keys!
26
+ return enum_for(:transform_keys!) { size } unless block_given?
19
27
  keys.each do |key|
20
28
  self[yield(key)] = delete(key)
21
29
  end
22
30
  self
23
- end
31
+ end unless method_defined? :transform_keys!
24
32
 
25
- # Return a new hash with all keys converted to strings.
33
+ # Returns a new hash with all keys converted to strings.
26
34
  #
27
35
  # hash = { name: 'Rob', age: '28' }
28
36
  #
29
37
  # hash.stringify_keys
30
- # #=> { "name" => "Rob", "age" => "28" }
38
+ # # => {"name"=>"Rob", "age"=>"28"}
31
39
  def stringify_keys
32
- transform_keys{ |key| key.to_s }
40
+ transform_keys(&:to_s)
33
41
  end
34
42
 
35
- # Destructively convert all keys to strings. Same as
43
+ # Destructively converts all keys to strings. Same as
36
44
  # +stringify_keys+, but modifies +self+.
37
45
  def stringify_keys!
38
- transform_keys!{ |key| key.to_s }
46
+ transform_keys!(&:to_s)
39
47
  end
40
48
 
41
- # Return a new hash with all keys converted to symbols, as long as
49
+ # Returns a new hash with all keys converted to symbols, as long as
42
50
  # they respond to +to_sym+.
43
51
  #
44
52
  # hash = { 'name' => 'Rob', 'age' => '28' }
45
53
  #
46
54
  # hash.symbolize_keys
47
- # #=> { name: "Rob", age: "28" }
55
+ # # => {:name=>"Rob", :age=>"28"}
48
56
  def symbolize_keys
49
- transform_keys{ |key| key.to_sym rescue key }
57
+ transform_keys { |key| key.to_sym rescue key }
50
58
  end
51
59
  alias_method :to_options, :symbolize_keys
52
60
 
53
- # Destructively convert all keys to symbols, as long as they respond
61
+ # Destructively converts all keys to symbols, as long as they respond
54
62
  # to +to_sym+. Same as +symbolize_keys+, but modifies +self+.
55
63
  def symbolize_keys!
56
- transform_keys!{ |key| key.to_sym rescue key }
64
+ transform_keys! { |key| key.to_sym rescue key }
57
65
  end
58
66
  alias_method :to_options!, :symbolize_keys!
59
67
 
60
- # Validate all keys in a hash match <tt>*valid_keys</tt>, raising ArgumentError
61
- # on a mismatch. Note that keys are NOT treated indifferently, meaning if you
62
- # use strings for keys but assert symbols as keys, this will fail.
68
+ # Validates all keys in a hash match <tt>*valid_keys</tt>, raising
69
+ # +ArgumentError+ on a mismatch.
70
+ #
71
+ # Note that keys are treated differently than HashWithIndifferentAccess,
72
+ # meaning that string and symbol keys will not match.
63
73
  #
64
- # { name: 'Rob', years: '28' }.assert_valid_keys(:name, :age) # => raises "ArgumentError: Unknown key: years"
65
- # { name: 'Rob', age: '28' }.assert_valid_keys('name', 'age') # => raises "ArgumentError: Unknown key: name"
74
+ # { name: 'Rob', years: '28' }.assert_valid_keys(:name, :age) # => raises "ArgumentError: Unknown key: :years. Valid keys are: :name, :age"
75
+ # { name: 'Rob', age: '28' }.assert_valid_keys('name', 'age') # => raises "ArgumentError: Unknown key: :name. Valid keys are: 'name', 'age'"
66
76
  # { name: 'Rob', age: '28' }.assert_valid_keys(:name, :age) # => passes, raises nothing
67
77
  def assert_valid_keys(*valid_keys)
68
78
  valid_keys.flatten!
69
79
  each_key do |k|
70
- raise ArgumentError.new("Unknown key: #{k}") unless valid_keys.include?(k)
80
+ unless valid_keys.include?(k)
81
+ raise ArgumentError.new("Unknown key: #{k.inspect}. Valid keys are: #{valid_keys.map(&:inspect).join(', ')}")
82
+ end
71
83
  end
72
84
  end
73
85
 
74
- # Return a new hash with all keys converted by the block operation.
86
+ # Returns a new hash with all keys converted by the block operation.
75
87
  # This includes the keys from the root hash and from all
76
88
  # nested hashes and arrays.
77
89
  #
78
90
  # hash = { person: { name: 'Rob', age: '28' } }
79
91
  #
80
92
  # hash.deep_transform_keys{ |key| key.to_s.upcase }
81
- # # => { "PERSON" => { "NAME" => "Rob", "AGE" => "28" } }
93
+ # # => {"PERSON"=>{"NAME"=>"Rob", "AGE"=>"28"}}
82
94
  def deep_transform_keys(&block)
83
95
  _deep_transform_keys_in_object(self, &block)
84
96
  end
85
97
 
86
- # Destructively convert all keys by using the block operation.
98
+ # Destructively converts all keys by using the block operation.
87
99
  # This includes the keys from the root hash and from all
88
100
  # nested hashes and arrays.
89
101
  def deep_transform_keys!(&block)
90
102
  _deep_transform_keys_in_object!(self, &block)
91
103
  end
92
104
 
93
- # Return a new hash with all keys converted to strings.
105
+ # Returns a new hash with all keys converted to strings.
94
106
  # This includes the keys from the root hash and from all
95
107
  # nested hashes and arrays.
96
108
  #
97
109
  # hash = { person: { name: 'Rob', age: '28' } }
98
110
  #
99
111
  # hash.deep_stringify_keys
100
- # # => { "person" => { "name" => "Rob", "age" => "28" } }
112
+ # # => {"person"=>{"name"=>"Rob", "age"=>"28"}}
101
113
  def deep_stringify_keys
102
- deep_transform_keys{ |key| key.to_s }
114
+ deep_transform_keys(&:to_s)
103
115
  end
104
116
 
105
- # Destructively convert all keys to strings.
117
+ # Destructively converts all keys to strings.
106
118
  # This includes the keys from the root hash and from all
107
119
  # nested hashes and arrays.
108
120
  def deep_stringify_keys!
109
- deep_transform_keys!{ |key| key.to_s }
121
+ deep_transform_keys!(&:to_s)
110
122
  end
111
123
 
112
- # Return a new hash with all keys converted to symbols, as long as
124
+ # Returns a new hash with all keys converted to symbols, as long as
113
125
  # they respond to +to_sym+. This includes the keys from the root hash
114
126
  # and from all nested hashes and arrays.
115
127
  #
116
128
  # hash = { 'person' => { 'name' => 'Rob', 'age' => '28' } }
117
129
  #
118
130
  # hash.deep_symbolize_keys
119
- # # => { person: { name: "Rob", age: "28" } }
131
+ # # => {:person=>{:name=>"Rob", :age=>"28"}}
120
132
  def deep_symbolize_keys
121
- deep_transform_keys{ |key| key.to_sym rescue key }
133
+ deep_transform_keys { |key| key.to_sym rescue key }
122
134
  end
123
135
 
124
- # Destructively convert all keys to symbols, as long as they respond
136
+ # Destructively converts all keys to symbols, as long as they respond
125
137
  # to +to_sym+. This includes the keys from the root hash and from all
126
138
  # nested hashes and arrays.
127
139
  def deep_symbolize_keys!
128
- deep_transform_keys!{ |key| key.to_sym rescue key }
140
+ deep_transform_keys! { |key| key.to_sym rescue key }
129
141
  end
130
142
 
131
143
  private
@@ -137,7 +149,7 @@ class Hash
137
149
  result[yield(key)] = _deep_transform_keys_in_object(value, &block)
138
150
  end
139
151
  when Array
140
- object.map {|e| _deep_transform_keys_in_object(e, &block) }
152
+ object.map { |e| _deep_transform_keys_in_object(e, &block) }
141
153
  else
142
154
  object
143
155
  end
@@ -152,7 +164,7 @@ class Hash
152
164
  end
153
165
  object
154
166
  when Array
155
- object.map! {|e| _deep_transform_keys_in_object!(e, &block)}
167
+ object.map! { |e| _deep_transform_keys_in_object!(e, &block) }
156
168
  else
157
169
  object
158
170
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Hash
2
4
  # Merges the caller into +other_hash+. For example,
3
5
  #
@@ -12,11 +14,12 @@ class Hash
12
14
  def reverse_merge(other_hash)
13
15
  other_hash.merge(self)
14
16
  end
17
+ alias_method :with_defaults, :reverse_merge
15
18
 
16
19
  # Destructive +reverse_merge+.
17
20
  def reverse_merge!(other_hash)
18
- # right wins if there is no left
19
- merge!( other_hash ){|key,left,right| left }
21
+ replace(reverse_merge(other_hash))
20
22
  end
21
23
  alias_method :reverse_update, :reverse_merge!
24
+ alias_method :with_defaults!, :reverse_merge!
22
25
  end
@@ -1,6 +1,14 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Hash
2
- # Slice a hash to include only the given keys. This is useful for
3
- # limiting an options hash to valid keys before passing to a method:
4
+ # Slices a hash to include only the given keys. Returns a hash containing
5
+ # the given keys.
6
+ #
7
+ # { a: 1, b: 2, c: 3, d: 4 }.slice(:a, :b)
8
+ # # => {:a=>1, :b=>2}
9
+ #
10
+ # This is useful for limiting an options hash to valid keys before
11
+ # passing to a method:
4
12
  #
5
13
  # def search(criteria = {})
6
14
  # criteria.assert_valid_keys(:mass, :velocity, :time)
@@ -13,9 +21,8 @@ class Hash
13
21
  # valid_keys = [:mass, :velocity, :time]
14
22
  # search(options.slice(*valid_keys))
15
23
  def slice(*keys)
16
- keys.map! { |key| convert_key(key) } if respond_to?(:convert_key, true)
17
- keys.each_with_object(self.class.new) { |k, hash| hash[k] = self[k] if has_key?(k) }
18
- end
24
+ keys.each_with_object(Hash.new) { |k, hash| hash[k] = self[k] if has_key?(k) }
25
+ end unless method_defined?(:slice)
19
26
 
20
27
  # Replaces the hash with only the given keys.
21
28
  # Returns a hash containing the removed key/value pairs.
@@ -23,7 +30,6 @@ class Hash
23
30
  # { a: 1, b: 2, c: 3, d: 4 }.slice!(:a, :b)
24
31
  # # => {:c=>3, :d=>4}
25
32
  def slice!(*keys)
26
- keys.map! { |key| convert_key(key) } if respond_to?(:convert_key, true)
27
33
  omit = slice(*self.keys - keys)
28
34
  hash = slice(*keys)
29
35
  hash.default = default
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Hash
4
+ # Returns a new hash with the results of running +block+ once for every value.
5
+ # The keys are unchanged.
6
+ #
7
+ # { a: 1, b: 2, c: 3 }.transform_values { |x| x * 2 } # => { a: 2, b: 4, c: 6 }
8
+ #
9
+ # If you do not provide a +block+, it will return an Enumerator
10
+ # for chaining with other methods:
11
+ #
12
+ # { a: 1, b: 2 }.transform_values.with_index { |v, i| [v, i].join.to_i } # => { a: 10, b: 21 }
13
+ def transform_values
14
+ return enum_for(:transform_values) { size } unless block_given?
15
+ return {} if empty?
16
+ result = self.class.new
17
+ each do |key, value|
18
+ result[key] = yield(value)
19
+ end
20
+ result
21
+ end unless method_defined? :transform_values
22
+
23
+ # Destructively converts all values using the +block+ operations.
24
+ # Same as +transform_values+ but modifies +self+.
25
+ def transform_values!
26
+ return enum_for(:transform_values!) { size } unless block_given?
27
+ each do |key, value|
28
+ self[key] = yield(value)
29
+ end
30
+ end unless method_defined? :transform_values!
31
+ # TODO: Remove this file when supporting only Ruby 2.4+.
32
+ end
@@ -1,8 +1,11 @@
1
- require 'active_support/core_ext/hash/conversions'
2
- require 'active_support/core_ext/hash/deep_merge'
3
- require 'active_support/core_ext/hash/diff'
4
- require 'active_support/core_ext/hash/except'
5
- require 'active_support/core_ext/hash/indifferent_access'
6
- require 'active_support/core_ext/hash/keys'
7
- require 'active_support/core_ext/hash/reverse_merge'
8
- require 'active_support/core_ext/hash/slice'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/hash/compact"
4
+ require "active_support/core_ext/hash/conversions"
5
+ require "active_support/core_ext/hash/deep_merge"
6
+ require "active_support/core_ext/hash/except"
7
+ require "active_support/core_ext/hash/indifferent_access"
8
+ require "active_support/core_ext/hash/keys"
9
+ require "active_support/core_ext/hash/reverse_merge"
10
+ require "active_support/core_ext/hash/slice"
11
+ require "active_support/core_ext/hash/transform_values"
@@ -1,4 +1,6 @@
1
- require 'active_support/inflector'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/inflector"
2
4
 
3
5
  class Integer
4
6
  # Ordinalize turns a number into an ordinal string used to denote the
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Integer
2
4
  # Check whether the integer is evenly divisible by the argument.
3
5
  #