activesupport 4.2.0 → 5.2.0

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 (254) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +366 -232
  3. data/MIT-LICENSE +2 -2
  4. data/README.rdoc +4 -5
  5. data/lib/active_support.rb +17 -7
  6. data/lib/active_support/all.rb +5 -3
  7. data/lib/active_support/array_inquirer.rb +48 -0
  8. data/lib/active_support/backtrace_cleaner.rb +7 -5
  9. data/lib/active_support/benchmarkable.rb +6 -4
  10. data/lib/active_support/builder.rb +3 -1
  11. data/lib/active_support/cache.rb +271 -177
  12. data/lib/active_support/cache/file_store.rb +41 -35
  13. data/lib/active_support/cache/mem_cache_store.rb +97 -88
  14. data/lib/active_support/cache/memory_store.rb +27 -30
  15. data/lib/active_support/cache/null_store.rb +7 -8
  16. data/lib/active_support/cache/redis_cache_store.rb +454 -0
  17. data/lib/active_support/cache/strategy/local_cache.rb +67 -34
  18. data/lib/active_support/cache/strategy/local_cache_middleware.rb +10 -9
  19. data/lib/active_support/callbacks.rb +654 -560
  20. data/lib/active_support/concern.rb +5 -3
  21. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +17 -0
  22. data/lib/active_support/concurrency/share_lock.rb +227 -0
  23. data/lib/active_support/configurable.rb +8 -5
  24. data/lib/active_support/core_ext.rb +3 -1
  25. data/lib/active_support/core_ext/array.rb +9 -6
  26. data/lib/active_support/core_ext/array/access.rb +29 -1
  27. data/lib/active_support/core_ext/array/conversions.rb +22 -18
  28. data/lib/active_support/core_ext/array/extract_options.rb +2 -0
  29. data/lib/active_support/core_ext/array/grouping.rb +11 -18
  30. data/lib/active_support/core_ext/array/inquiry.rb +19 -0
  31. data/lib/active_support/core_ext/array/prepend_and_append.rb +5 -3
  32. data/lib/active_support/core_ext/array/wrap.rb +7 -4
  33. data/lib/active_support/core_ext/benchmark.rb +3 -1
  34. data/lib/active_support/core_ext/big_decimal.rb +3 -1
  35. data/lib/active_support/core_ext/big_decimal/conversions.rb +10 -12
  36. data/lib/active_support/core_ext/class.rb +4 -3
  37. data/lib/active_support/core_ext/class/attribute.rb +41 -22
  38. data/lib/active_support/core_ext/class/attribute_accessors.rb +3 -1
  39. data/lib/active_support/core_ext/class/subclasses.rb +20 -8
  40. data/lib/active_support/core_ext/date.rb +6 -4
  41. data/lib/active_support/core_ext/date/acts_like.rb +3 -1
  42. data/lib/active_support/core_ext/date/blank.rb +14 -0
  43. data/lib/active_support/core_ext/date/calculations.rb +11 -9
  44. data/lib/active_support/core_ext/date/conversions.rb +31 -23
  45. data/lib/active_support/core_ext/date/zones.rb +4 -2
  46. data/lib/active_support/core_ext/date_and_time/calculations.rb +179 -56
  47. data/lib/active_support/core_ext/date_and_time/compatibility.rb +16 -0
  48. data/lib/active_support/core_ext/date_and_time/zones.rb +12 -12
  49. data/lib/active_support/core_ext/date_time.rb +7 -4
  50. data/lib/active_support/core_ext/date_time/acts_like.rb +4 -2
  51. data/lib/active_support/core_ext/date_time/blank.rb +14 -0
  52. data/lib/active_support/core_ext/date_time/calculations.rb +58 -20
  53. data/lib/active_support/core_ext/date_time/compatibility.rb +18 -0
  54. data/lib/active_support/core_ext/date_time/conversions.rb +16 -12
  55. data/lib/active_support/core_ext/digest/uuid.rb +7 -5
  56. data/lib/active_support/core_ext/enumerable.rb +107 -28
  57. data/lib/active_support/core_ext/file.rb +3 -1
  58. data/lib/active_support/core_ext/file/atomic.rb +38 -31
  59. data/lib/active_support/core_ext/hash.rb +11 -9
  60. data/lib/active_support/core_ext/hash/compact.rb +24 -15
  61. data/lib/active_support/core_ext/hash/conversions.rb +63 -43
  62. data/lib/active_support/core_ext/hash/deep_merge.rb +9 -13
  63. data/lib/active_support/core_ext/hash/except.rb +11 -8
  64. data/lib/active_support/core_ext/hash/indifferent_access.rb +4 -3
  65. data/lib/active_support/core_ext/hash/keys.rb +33 -27
  66. data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
  67. data/lib/active_support/core_ext/hash/slice.rb +8 -8
  68. data/lib/active_support/core_ext/hash/transform_values.rb +16 -7
  69. data/lib/active_support/core_ext/integer.rb +5 -3
  70. data/lib/active_support/core_ext/integer/inflections.rb +3 -1
  71. data/lib/active_support/core_ext/integer/multiple.rb +2 -0
  72. data/lib/active_support/core_ext/integer/time.rb +11 -33
  73. data/lib/active_support/core_ext/kernel.rb +6 -5
  74. data/lib/active_support/core_ext/kernel/agnostics.rb +2 -0
  75. data/lib/active_support/core_ext/kernel/concern.rb +5 -1
  76. data/lib/active_support/core_ext/kernel/reporting.rb +4 -83
  77. data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
  78. data/lib/active_support/core_ext/load_error.rb +3 -22
  79. data/lib/active_support/core_ext/marshal.rb +13 -10
  80. data/lib/active_support/core_ext/module.rb +14 -11
  81. data/lib/active_support/core_ext/module/aliasing.rb +6 -44
  82. data/lib/active_support/core_ext/module/anonymous.rb +12 -1
  83. data/lib/active_support/core_ext/module/attr_internal.rb +8 -9
  84. data/lib/active_support/core_ext/module/attribute_accessors.rb +43 -40
  85. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +150 -0
  86. data/lib/active_support/core_ext/module/concerning.rb +11 -12
  87. data/lib/active_support/core_ext/module/delegation.rb +121 -39
  88. data/lib/active_support/core_ext/module/deprecation.rb +4 -2
  89. data/lib/active_support/core_ext/module/introspection.rb +9 -9
  90. data/lib/active_support/core_ext/module/reachable.rb +5 -2
  91. data/lib/active_support/core_ext/module/redefine_method.rb +49 -0
  92. data/lib/active_support/core_ext/module/remove_method.rb +8 -3
  93. data/lib/active_support/core_ext/name_error.rb +22 -2
  94. data/lib/active_support/core_ext/numeric.rb +6 -3
  95. data/lib/active_support/core_ext/numeric/bytes.rb +22 -0
  96. data/lib/active_support/core_ext/numeric/conversions.rb +79 -74
  97. data/lib/active_support/core_ext/numeric/inquiry.rb +28 -0
  98. data/lib/active_support/core_ext/numeric/time.rb +35 -38
  99. data/lib/active_support/core_ext/object.rb +14 -13
  100. data/lib/active_support/core_ext/object/acts_like.rb +12 -1
  101. data/lib/active_support/core_ext/object/blank.rb +29 -4
  102. data/lib/active_support/core_ext/object/conversions.rb +6 -4
  103. data/lib/active_support/core_ext/object/deep_dup.rb +13 -4
  104. data/lib/active_support/core_ext/object/duplicable.rb +98 -45
  105. data/lib/active_support/core_ext/object/inclusion.rb +5 -3
  106. data/lib/active_support/core_ext/object/instance_variables.rb +3 -1
  107. data/lib/active_support/core_ext/object/json.rb +49 -19
  108. data/lib/active_support/core_ext/object/to_param.rb +3 -1
  109. data/lib/active_support/core_ext/object/to_query.rb +6 -4
  110. data/lib/active_support/core_ext/object/try.rb +70 -22
  111. data/lib/active_support/core_ext/object/with_options.rb +16 -3
  112. data/lib/active_support/core_ext/range.rb +7 -4
  113. data/lib/active_support/core_ext/range/conversions.rb +27 -7
  114. data/lib/active_support/core_ext/range/each.rb +19 -17
  115. data/lib/active_support/core_ext/range/include_range.rb +21 -19
  116. data/lib/active_support/core_ext/range/include_time_with_zone.rb +23 -0
  117. data/lib/active_support/core_ext/range/overlaps.rb +2 -0
  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.rb +15 -13
  121. data/lib/active_support/core_ext/string/access.rb +9 -7
  122. data/lib/active_support/core_ext/string/behavior.rb +3 -1
  123. data/lib/active_support/core_ext/string/conversions.rb +8 -5
  124. data/lib/active_support/core_ext/string/exclude.rb +2 -0
  125. data/lib/active_support/core_ext/string/filters.rb +10 -8
  126. data/lib/active_support/core_ext/string/indent.rb +6 -4
  127. data/lib/active_support/core_ext/string/inflections.rb +61 -24
  128. data/lib/active_support/core_ext/string/inquiry.rb +3 -1
  129. data/lib/active_support/core_ext/string/multibyte.rb +15 -7
  130. data/lib/active_support/core_ext/string/output_safety.rb +35 -35
  131. data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -0
  132. data/lib/active_support/core_ext/string/strip.rb +4 -5
  133. data/lib/active_support/core_ext/string/zones.rb +4 -2
  134. data/lib/active_support/core_ext/time.rb +7 -5
  135. data/lib/active_support/core_ext/time/acts_like.rb +3 -1
  136. data/lib/active_support/core_ext/time/calculations.rb +101 -51
  137. data/lib/active_support/core_ext/time/compatibility.rb +16 -0
  138. data/lib/active_support/core_ext/time/conversions.rb +20 -13
  139. data/lib/active_support/core_ext/time/zones.rb +41 -7
  140. data/lib/active_support/core_ext/uri.rb +5 -4
  141. data/lib/active_support/current_attributes.rb +195 -0
  142. data/lib/active_support/dependencies.rb +143 -160
  143. data/lib/active_support/dependencies/autoload.rb +2 -0
  144. data/lib/active_support/dependencies/interlock.rb +57 -0
  145. data/lib/active_support/deprecation.rb +12 -9
  146. data/lib/active_support/deprecation/behaviors.rb +41 -12
  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 +54 -21
  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/descendants_tracker.rb +2 -0
  153. data/lib/active_support/digest.rb +20 -0
  154. data/lib/active_support/duration.rb +326 -30
  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/encrypted_configuration.rb +49 -0
  158. data/lib/active_support/encrypted_file.rb +99 -0
  159. data/lib/active_support/evented_file_update_checker.rb +205 -0
  160. data/lib/active_support/execution_wrapper.rb +128 -0
  161. data/lib/active_support/executor.rb +8 -0
  162. data/lib/active_support/file_update_checker.rb +63 -37
  163. data/lib/active_support/gem_version.rb +4 -2
  164. data/lib/active_support/gzip.rb +7 -5
  165. data/lib/active_support/hash_with_indifferent_access.rb +130 -30
  166. data/lib/active_support/i18n.rb +8 -6
  167. data/lib/active_support/i18n_railtie.rb +34 -14
  168. data/lib/active_support/inflections.rb +13 -11
  169. data/lib/active_support/inflector.rb +7 -5
  170. data/lib/active_support/inflector/inflections.rb +61 -12
  171. data/lib/active_support/inflector/methods.rb +161 -136
  172. data/lib/active_support/inflector/transliterate.rb +48 -27
  173. data/lib/active_support/json.rb +4 -2
  174. data/lib/active_support/json/decoding.rb +16 -13
  175. data/lib/active_support/json/encoding.rb +15 -57
  176. data/lib/active_support/key_generator.rb +25 -25
  177. data/lib/active_support/lazy_load_hooks.rb +50 -20
  178. data/lib/active_support/locale/en.yml +2 -0
  179. data/lib/active_support/log_subscriber.rb +13 -10
  180. data/lib/active_support/log_subscriber/test_helper.rb +14 -12
  181. data/lib/active_support/logger.rb +54 -3
  182. data/lib/active_support/logger_silence.rb +12 -7
  183. data/lib/active_support/logger_thread_safe_level.rb +33 -0
  184. data/lib/active_support/message_encryptor.rb +173 -51
  185. data/lib/active_support/message_verifier.rb +150 -17
  186. data/lib/active_support/messages/metadata.rb +71 -0
  187. data/lib/active_support/messages/rotation_configuration.rb +22 -0
  188. data/lib/active_support/messages/rotator.rb +56 -0
  189. data/lib/active_support/multibyte.rb +4 -2
  190. data/lib/active_support/multibyte/chars.rb +37 -24
  191. data/lib/active_support/multibyte/unicode.rb +100 -96
  192. data/lib/active_support/notifications.rb +11 -7
  193. data/lib/active_support/notifications/fanout.rb +10 -8
  194. data/lib/active_support/notifications/instrumenter.rb +27 -7
  195. data/lib/active_support/number_helper.rb +94 -68
  196. data/lib/active_support/number_helper/number_converter.rb +13 -11
  197. data/lib/active_support/number_helper/number_to_currency_converter.rb +9 -9
  198. data/lib/active_support/number_helper/number_to_delimited_converter.rb +9 -3
  199. data/lib/active_support/number_helper/number_to_human_converter.rb +11 -9
  200. data/lib/active_support/number_helper/number_to_human_size_converter.rb +9 -8
  201. data/lib/active_support/number_helper/number_to_percentage_converter.rb +3 -1
  202. data/lib/active_support/number_helper/number_to_phone_converter.rb +13 -4
  203. data/lib/active_support/number_helper/number_to_rounded_converter.rb +23 -56
  204. data/lib/active_support/number_helper/rounding_helper.rb +66 -0
  205. data/lib/active_support/option_merger.rb +3 -1
  206. data/lib/active_support/ordered_hash.rb +6 -4
  207. data/lib/active_support/ordered_options.rb +22 -4
  208. data/lib/active_support/per_thread_registry.rb +13 -6
  209. data/lib/active_support/proxy_object.rb +2 -0
  210. data/lib/active_support/rails.rb +16 -8
  211. data/lib/active_support/railtie.rb +43 -9
  212. data/lib/active_support/reloader.rb +131 -0
  213. data/lib/active_support/rescuable.rb +108 -53
  214. data/lib/active_support/security_utils.rb +17 -6
  215. data/lib/active_support/string_inquirer.rb +11 -3
  216. data/lib/active_support/subscriber.rb +15 -14
  217. data/lib/active_support/tagged_logging.rb +14 -11
  218. data/lib/active_support/test_case.rb +18 -46
  219. data/lib/active_support/testing/assertions.rb +137 -20
  220. data/lib/active_support/testing/autorun.rb +4 -2
  221. data/lib/active_support/testing/constant_lookup.rb +2 -1
  222. data/lib/active_support/testing/declarative.rb +3 -1
  223. data/lib/active_support/testing/deprecation.rb +14 -10
  224. data/lib/active_support/testing/file_fixtures.rb +36 -0
  225. data/lib/active_support/testing/isolation.rb +34 -25
  226. data/lib/active_support/testing/method_call_assertions.rb +43 -0
  227. data/lib/active_support/testing/setup_and_teardown.rb +12 -3
  228. data/lib/active_support/testing/stream.rb +44 -0
  229. data/lib/active_support/testing/tagged_logging.rb +3 -1
  230. data/lib/active_support/testing/time_helpers.rb +96 -27
  231. data/lib/active_support/time.rb +14 -12
  232. data/lib/active_support/time_with_zone.rb +195 -53
  233. data/lib/active_support/values/time_zone.rb +200 -61
  234. data/lib/active_support/values/unicode_tables.dat +0 -0
  235. data/lib/active_support/version.rb +3 -1
  236. data/lib/active_support/xml_mini.rb +69 -51
  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. metadata +55 -43
  244. data/lib/active_support/concurrency/latch.rb +0 -27
  245. data/lib/active_support/core_ext/big_decimal/yaml_conversions.rb +0 -14
  246. data/lib/active_support/core_ext/class/delegating_attributes.rb +0 -45
  247. data/lib/active_support/core_ext/date_time/zones.rb +0 -6
  248. data/lib/active_support/core_ext/kernel/debugger.rb +0 -10
  249. data/lib/active_support/core_ext/module/method_transplanting.rb +0 -11
  250. data/lib/active_support/core_ext/module/qualified_const.rb +0 -52
  251. data/lib/active_support/core_ext/object/itself.rb +0 -15
  252. data/lib/active_support/core_ext/struct.rb +0 -6
  253. data/lib/active_support/core_ext/thread.rb +0 -86
  254. data/lib/active_support/core_ext/time/marshal.rb +0 -30
@@ -1 +1,3 @@
1
- require 'active_support/core_ext/file/atomic'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/file/atomic"
@@ -1,4 +1,6 @@
1
- require 'fileutils'
1
+ # frozen_string_literal: true
2
+
3
+ require "fileutils"
2
4
 
3
5
  class File
4
6
  # Write to a file atomically. Useful for situations where you don't
@@ -8,51 +10,56 @@ class File
8
10
  # file.write('hello')
9
11
  # end
10
12
  #
11
- # If your temp directory is not on the same filesystem as the file you're
12
- # trying to write, you can provide a different temporary directory.
13
+ # This method needs to create a temporary file. By default it will create it
14
+ # in the same directory as the destination file. If you don't like this
15
+ # behavior you can provide a different directory but it must be on the
16
+ # same physical filesystem as the file you're trying to write.
13
17
  #
14
18
  # File.atomic_write('/data/something.important', '/data/tmp') do |file|
15
19
  # file.write('hello')
16
20
  # end
17
- def self.atomic_write(file_name, temp_dir = Dir.tmpdir)
18
- require 'tempfile' unless defined?(Tempfile)
19
- require 'fileutils' unless defined?(FileUtils)
20
-
21
- temp_file = Tempfile.new(basename(file_name), temp_dir)
22
- temp_file.binmode
23
- yield temp_file
24
- temp_file.close
25
-
26
- if File.exist?(file_name)
27
- # Get original file permissions
28
- old_stat = stat(file_name)
29
- else
30
- # If not possible, probe which are the default permissions in the
31
- # destination directory.
32
- old_stat = probe_stat_in(dirname(file_name))
33
- end
21
+ def self.atomic_write(file_name, temp_dir = dirname(file_name))
22
+ require "tempfile" unless defined?(Tempfile)
23
+
24
+ Tempfile.open(".#{basename(file_name)}", temp_dir) do |temp_file|
25
+ temp_file.binmode
26
+ return_val = yield temp_file
27
+ temp_file.close
28
+
29
+ old_stat = if exist?(file_name)
30
+ # Get original file permissions
31
+ stat(file_name)
32
+ elsif temp_dir != dirname(file_name)
33
+ # If not possible, probe which are the default permissions in the
34
+ # destination directory.
35
+ probe_stat_in(dirname(file_name))
36
+ end
34
37
 
35
- # Overwrite original file with temp file
36
- FileUtils.mv(temp_file.path, file_name)
38
+ if old_stat
39
+ # Set correct permissions on new file
40
+ begin
41
+ chown(old_stat.uid, old_stat.gid, temp_file.path)
42
+ # This operation will affect filesystem ACL's
43
+ chmod(old_stat.mode, temp_file.path)
44
+ rescue Errno::EPERM, Errno::EACCES
45
+ # Changing file ownership failed, moving on.
46
+ end
47
+ end
37
48
 
38
- # Set correct permissions on new file
39
- begin
40
- chown(old_stat.uid, old_stat.gid, file_name)
41
- # This operation will affect filesystem ACL's
42
- chmod(old_stat.mode, file_name)
43
- rescue Errno::EPERM, Errno::EACCES
44
- # Changing file ownership failed, moving on.
49
+ # Overwrite original file with temp file
50
+ rename(temp_file.path, file_name)
51
+ return_val
45
52
  end
46
53
  end
47
54
 
48
55
  # Private utility method.
49
56
  def self.probe_stat_in(dir) #:nodoc:
50
57
  basename = [
51
- '.permissions_check',
58
+ ".permissions_check",
52
59
  Thread.current.object_id,
53
60
  Process.pid,
54
61
  rand(1000000)
55
- ].join('.')
62
+ ].join(".")
56
63
 
57
64
  file_name = join(dir, basename)
58
65
  FileUtils.touch(file_name)
@@ -1,9 +1,11 @@
1
- require 'active_support/core_ext/hash/compact'
2
- require 'active_support/core_ext/hash/conversions'
3
- require 'active_support/core_ext/hash/deep_merge'
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'
9
- require 'active_support/core_ext/hash/transform_values'
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,20 +1,29 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Hash
2
- # Returns a hash with non +nil+ values.
3
- #
4
- # hash = { a: true, b: false, c: nil}
5
- # hash.compact # => { a: true, b: false}
6
- # hash # => { a: true, b: false, c: nil}
7
- # { c: nil }.compact # => {}
8
- def compact
9
- self.select { |_, value| !value.nil? }
4
+ unless Hash.instance_methods(false).include?(:compact)
5
+ # Returns a hash with non +nil+ values.
6
+ #
7
+ # hash = { a: true, b: false, c: nil }
8
+ # hash.compact # => { a: true, b: false }
9
+ # hash # => { a: true, b: false, c: nil }
10
+ # { c: nil }.compact # => {}
11
+ # { c: true }.compact # => { c: true }
12
+ def compact
13
+ select { |_, value| !value.nil? }
14
+ end
10
15
  end
11
16
 
12
- # Replaces current hash with non +nil+ values.
13
- #
14
- # hash = { a: true, b: false, c: nil}
15
- # hash.compact! # => { a: true, b: false}
16
- # hash # => { a: true, b: false}
17
- def compact!
18
- self.reject! { |_, value| value.nil? }
17
+ unless Hash.instance_methods(false).include?(:compact!)
18
+ # Replaces current hash with non +nil+ values.
19
+ # Returns +nil+ if no changes were made, otherwise returns the hash.
20
+ #
21
+ # hash = { a: true, b: false, c: nil }
22
+ # hash.compact! # => { a: true, b: false }
23
+ # hash # => { a: true, b: false }
24
+ # { c: true }.compact! # => nil
25
+ def compact!
26
+ reject! { |_, value| value.nil? }
27
+ end
19
28
  end
20
29
  end
@@ -1,11 +1,13 @@
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:
@@ -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>.
@@ -55,8 +57,7 @@ class Hash
55
57
  #
56
58
  # XML_TYPE_NAMES = {
57
59
  # "Symbol" => "symbol",
58
- # "Fixnum" => "integer",
59
- # "Bignum" => "integer",
60
+ # "Integer" => "integer",
60
61
  # "BigDecimal" => "decimal",
61
62
  # "Float" => "float",
62
63
  # "TrueClass" => "boolean",
@@ -72,11 +73,11 @@ class Hash
72
73
  # configure your own builder with the <tt>:builder</tt> option. The method also accepts
73
74
  # options like <tt>:dasherize</tt> and friends, they are forwarded to the builder.
74
75
  def to_xml(options = {})
75
- require 'active_support/builder' unless defined?(Builder)
76
+ require "active_support/builder" unless defined?(Builder)
76
77
 
77
78
  options = options.dup
78
79
  options[:indent] ||= 2
79
- options[:root] ||= 'hash'
80
+ options[:root] ||= "hash"
80
81
  options[:builder] ||= Builder::XmlMarkup.new(indent: options[:indent])
81
82
 
82
83
  builder = options[:builder]
@@ -106,7 +107,25 @@ class Hash
106
107
  # # => {"hash"=>{"foo"=>1, "bar"=>2}}
107
108
  #
108
109
  # +DisallowedType+ is raised if the XML contains attributes with <tt>type="yaml"</tt> or
109
- # <tt>type="symbol"</tt>. Use <tt>Hash.from_trusted_xml</tt> to parse this XML.
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.
110
129
  def from_xml(xml, disallowed_types = nil)
111
130
  ActiveSupport::XMLConverter.new(xml, disallowed_types).to_h
112
131
  end
@@ -120,6 +139,8 @@ end
120
139
 
121
140
  module ActiveSupport
122
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.
123
144
  class DisallowedType < StandardError
124
145
  def initialize(type)
125
146
  super "Disallowed type attribute: #{type.inspect}"
@@ -140,36 +161,36 @@ module ActiveSupport
140
161
  private
141
162
  def normalize_keys(params)
142
163
  case params
143
- when Hash
144
- Hash[params.map { |k,v| [k.to_s.tr('-', '_'), normalize_keys(v)] } ]
145
- when Array
146
- params.map { |v| normalize_keys(v) }
147
- else
148
- 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
149
170
  end
150
171
  end
151
172
 
152
173
  def deep_to_h(value)
153
174
  case value
154
- when Hash
155
- process_hash(value)
156
- when Array
157
- process_array(value)
158
- when String
159
- value
160
- else
161
- 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}"
162
183
  end
163
184
  end
164
185
 
165
186
  def process_hash(value)
166
- if value.include?('type') && !value['type'].is_a?(Hash) && @disallowed_types.include?(value['type'])
167
- raise DisallowedType, value['type']
187
+ if value.include?("type") && !value["type"].is_a?(Hash) && @disallowed_types.include?(value["type"])
188
+ raise DisallowedType, value["type"]
168
189
  end
169
190
 
170
191
  if become_array?(value)
171
- _, entries = Array.wrap(value.detect { |k,v| not v.is_a?(String) })
172
- 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?)
173
194
  []
174
195
  else
175
196
  case entries
@@ -185,28 +206,28 @@ module ActiveSupport
185
206
  process_content(value)
186
207
 
187
208
  elsif become_empty_string?(value)
188
- ''
209
+ ""
189
210
  elsif become_hash?(value)
190
- 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)] }]
191
212
 
192
213
  # Turn { files: { file: #<StringIO> } } into { files: #<StringIO> } so it is compatible with
193
214
  # how multipart uploaded files from HTML appear
194
- xml_value['file'].is_a?(StringIO) ? xml_value['file'] : xml_value
215
+ xml_value["file"].is_a?(StringIO) ? xml_value["file"] : xml_value
195
216
  end
196
217
  end
197
218
 
198
219
  def become_content?(value)
199
- 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?))
200
221
  end
201
222
 
202
223
  def become_array?(value)
203
- value['type'] == 'array'
224
+ value["type"] == "array"
204
225
  end
205
226
 
206
227
  def become_empty_string?(value)
207
228
  # { "string" => true }
208
229
  # No tests fail when the second term is removed.
209
- value['type'] == 'string' && value['nil'] != 'true'
230
+ value["type"] == "string" && value["nil"] != "true"
210
231
  end
211
232
 
212
233
  def become_hash?(value)
@@ -215,19 +236,19 @@ module ActiveSupport
215
236
 
216
237
  def nothing?(value)
217
238
  # blank or nil parsed values are represented by nil
218
- value.blank? || value['nil'] == 'true'
239
+ value.blank? || value["nil"] == "true"
219
240
  end
220
241
 
221
242
  def garbage?(value)
222
243
  # If the type is the only element which makes it then
223
244
  # this still makes the value nil, except if type is
224
245
  # an XML node(where type['value'] is a Hash)
225
- value['type'] && !value['type'].is_a?(::Hash) && value.size == 1
246
+ value["type"] && !value["type"].is_a?(::Hash) && value.size == 1
226
247
  end
227
248
 
228
249
  def process_content(value)
229
- content = value['__content__']
230
- if parser = ActiveSupport::XmlMini::PARSING[value['type']]
250
+ content = value["__content__"]
251
+ if parser = ActiveSupport::XmlMini::PARSING[value["type"]]
231
252
  parser.arity == 1 ? parser.call(content) : parser.call(content, value)
232
253
  else
233
254
  content
@@ -238,6 +259,5 @@ module ActiveSupport
238
259
  value.map! { |i| deep_to_h(i) }
239
260
  value.length > 1 ? value : value.first
240
261
  end
241
-
242
262
  end
243
263
  end
@@ -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,8 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Hash
2
- # Returns a hash that includes everything but the given keys.
3
- # hash = { a: true, b: false, c: nil}
4
- # hash.except(:c) # => { a: true, b: false}
5
- # hash # => { a: true, b: false, c: nil}
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 }
6
9
  #
7
10
  # This is useful for limiting a set of parameters to everything but a few known toggles:
8
11
  # @person.update(params[:person].except(:admin))
@@ -10,10 +13,10 @@ class Hash
10
13
  dup.except!(*keys)
11
14
  end
12
15
 
13
- # Replaces the hash without the given keys.
14
- # hash = { a: true, b: false, c: nil}
15
- # hash.except!(:c) # => { a: true, b: false}
16
- # hash # => { a: true, b: false }
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 }
17
20
  def except!(*keys)
18
21
  keys.each { |key| delete(key) }
19
22
  self