activesupport 1.2.4 → 8.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (309) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +505 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.rdoc +40 -0
  5. data/lib/active_support/actionable_error.rb +50 -0
  6. data/lib/active_support/all.rb +5 -0
  7. data/lib/active_support/array_inquirer.rb +50 -0
  8. data/lib/active_support/backtrace_cleaner.rb +234 -0
  9. data/lib/active_support/benchmark.rb +21 -0
  10. data/lib/active_support/benchmarkable.rb +53 -0
  11. data/lib/active_support/broadcast_logger.rb +238 -0
  12. data/lib/active_support/builder.rb +8 -0
  13. data/lib/active_support/cache/coder.rb +153 -0
  14. data/lib/active_support/cache/entry.rb +134 -0
  15. data/lib/active_support/cache/file_store.rb +244 -0
  16. data/lib/active_support/cache/mem_cache_store.rb +288 -0
  17. data/lib/active_support/cache/memory_store.rb +264 -0
  18. data/lib/active_support/cache/null_store.rb +62 -0
  19. data/lib/active_support/cache/redis_cache_store.rb +498 -0
  20. data/lib/active_support/cache/serializer_with_fallback.rb +152 -0
  21. data/lib/active_support/cache/strategy/local_cache.rb +246 -0
  22. data/lib/active_support/cache/strategy/local_cache_middleware.rb +45 -0
  23. data/lib/active_support/cache.rb +1170 -0
  24. data/lib/active_support/callbacks.rb +960 -0
  25. data/lib/active_support/class_attribute.rb +33 -0
  26. data/lib/active_support/code_generator.rb +79 -0
  27. data/lib/active_support/concern.rb +217 -0
  28. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +18 -0
  29. data/lib/active_support/concurrency/null_lock.rb +13 -0
  30. data/lib/active_support/concurrency/share_lock.rb +225 -0
  31. data/lib/active_support/concurrency/thread_monitor.rb +55 -0
  32. data/lib/active_support/configurable.rb +193 -0
  33. data/lib/active_support/configuration_file.rb +60 -0
  34. data/lib/active_support/continuous_integration.rb +145 -0
  35. data/lib/active_support/core_ext/array/access.rb +100 -0
  36. data/lib/active_support/core_ext/array/conversions.rb +209 -26
  37. data/lib/active_support/core_ext/array/extract.rb +21 -0
  38. data/lib/active_support/core_ext/array/extract_options.rb +31 -0
  39. data/lib/active_support/core_ext/array/grouping.rb +109 -0
  40. data/lib/active_support/core_ext/array/inquiry.rb +19 -0
  41. data/lib/active_support/core_ext/array/wrap.rb +48 -0
  42. data/lib/active_support/core_ext/array.rb +8 -4
  43. data/lib/active_support/core_ext/benchmark.rb +6 -0
  44. data/lib/active_support/core_ext/big_decimal/conversions.rb +14 -0
  45. data/lib/active_support/core_ext/big_decimal.rb +3 -0
  46. data/lib/active_support/core_ext/class/attribute.rb +137 -0
  47. data/lib/active_support/core_ext/class/attribute_accessors.rb +6 -0
  48. data/lib/active_support/core_ext/class/subclasses.rb +24 -0
  49. data/lib/active_support/core_ext/class.rb +4 -0
  50. data/lib/active_support/core_ext/date/acts_like.rb +10 -0
  51. data/lib/active_support/core_ext/date/blank.rb +18 -0
  52. data/lib/active_support/core_ext/date/calculations.rb +161 -0
  53. data/lib/active_support/core_ext/date/conversions.rb +95 -28
  54. data/lib/active_support/core_ext/date/zones.rb +8 -0
  55. data/lib/active_support/core_ext/date.rb +6 -5
  56. data/lib/active_support/core_ext/date_and_time/calculations.rb +374 -0
  57. data/lib/active_support/core_ext/date_and_time/compatibility.rb +23 -0
  58. data/lib/active_support/core_ext/date_and_time/zones.rb +40 -0
  59. data/lib/active_support/core_ext/date_time/acts_like.rb +16 -0
  60. data/lib/active_support/core_ext/date_time/blank.rb +18 -0
  61. data/lib/active_support/core_ext/date_time/calculations.rb +215 -0
  62. data/lib/active_support/core_ext/date_time/compatibility.rb +16 -0
  63. data/lib/active_support/core_ext/date_time/conversions.rb +108 -0
  64. data/lib/active_support/core_ext/date_time.rb +7 -0
  65. data/lib/active_support/core_ext/digest/uuid.rb +76 -0
  66. data/lib/active_support/core_ext/digest.rb +3 -0
  67. data/lib/active_support/core_ext/enumerable.rb +277 -7
  68. data/lib/active_support/core_ext/erb/util.rb +201 -0
  69. data/lib/active_support/core_ext/file/atomic.rb +72 -0
  70. data/lib/active_support/core_ext/file.rb +3 -0
  71. data/lib/active_support/core_ext/hash/conversions.rb +262 -0
  72. data/lib/active_support/core_ext/hash/deep_merge.rb +43 -0
  73. data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
  74. data/lib/active_support/core_ext/hash/except.rb +12 -0
  75. data/lib/active_support/core_ext/hash/indifferent_access.rb +19 -55
  76. data/lib/active_support/core_ext/hash/keys.rb +134 -44
  77. data/lib/active_support/core_ext/hash/reverse_merge.rb +22 -22
  78. data/lib/active_support/core_ext/hash/slice.rb +27 -0
  79. data/lib/active_support/core_ext/hash.rb +9 -8
  80. data/lib/active_support/core_ext/integer/inflections.rb +29 -13
  81. data/lib/active_support/core_ext/integer/multiple.rb +12 -0
  82. data/lib/active_support/core_ext/integer/time.rb +22 -0
  83. data/lib/active_support/core_ext/integer.rb +4 -6
  84. data/lib/active_support/core_ext/kernel/concern.rb +14 -0
  85. data/lib/active_support/core_ext/kernel/reporting.rb +45 -0
  86. data/lib/active_support/core_ext/kernel/singleton_class.rb +8 -0
  87. data/lib/active_support/core_ext/kernel.rb +4 -78
  88. data/lib/active_support/core_ext/load_error.rb +6 -35
  89. data/lib/active_support/core_ext/module/aliasing.rb +31 -0
  90. data/lib/active_support/core_ext/module/anonymous.rb +30 -0
  91. data/lib/active_support/core_ext/module/attr_internal.rb +48 -0
  92. data/lib/active_support/core_ext/module/attribute_accessors.rb +214 -0
  93. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +175 -0
  94. data/lib/active_support/core_ext/module/concerning.rb +140 -0
  95. data/lib/active_support/core_ext/module/delegation.rb +225 -0
  96. data/lib/active_support/core_ext/module/deprecation.rb +25 -0
  97. data/lib/active_support/core_ext/module/introspection.rb +65 -0
  98. data/lib/active_support/core_ext/module/redefine_method.rb +40 -0
  99. data/lib/active_support/core_ext/module/remove_method.rb +17 -0
  100. data/lib/active_support/core_ext/module.rb +13 -0
  101. data/lib/active_support/core_ext/name_error.rb +59 -0
  102. data/lib/active_support/core_ext/numeric/bytes.rb +73 -42
  103. data/lib/active_support/core_ext/numeric/conversions.rb +145 -0
  104. data/lib/active_support/core_ext/numeric/time.rb +64 -57
  105. data/lib/active_support/core_ext/numeric.rb +4 -6
  106. data/lib/active_support/core_ext/object/acts_like.rb +45 -0
  107. data/lib/active_support/core_ext/object/blank.rb +199 -0
  108. data/lib/active_support/core_ext/object/conversions.rb +6 -0
  109. data/lib/active_support/core_ext/object/deep_dup.rb +71 -0
  110. data/lib/active_support/core_ext/object/duplicable.rb +69 -0
  111. data/lib/active_support/core_ext/object/inclusion.rb +37 -0
  112. data/lib/active_support/core_ext/object/instance_variables.rb +32 -0
  113. data/lib/active_support/core_ext/object/json.rb +267 -0
  114. data/lib/active_support/core_ext/object/to_param.rb +3 -0
  115. data/lib/active_support/core_ext/object/to_query.rb +93 -0
  116. data/lib/active_support/core_ext/object/try.rb +158 -0
  117. data/lib/active_support/core_ext/object/with.rb +46 -0
  118. data/lib/active_support/core_ext/object/with_options.rb +101 -0
  119. data/lib/active_support/core_ext/object.rb +17 -0
  120. data/lib/active_support/core_ext/pathname/blank.rb +20 -0
  121. data/lib/active_support/core_ext/pathname/existence.rb +23 -0
  122. data/lib/active_support/core_ext/pathname.rb +4 -0
  123. data/lib/active_support/core_ext/range/compare_range.rb +57 -0
  124. data/lib/active_support/core_ext/range/conversions.rb +58 -17
  125. data/lib/active_support/core_ext/range/overlap.rb +40 -0
  126. data/lib/active_support/core_ext/range/sole.rb +17 -0
  127. data/lib/active_support/core_ext/range.rb +5 -4
  128. data/lib/active_support/core_ext/regexp.rb +14 -0
  129. data/lib/active_support/core_ext/securerandom.rb +57 -0
  130. data/lib/active_support/core_ext/string/access.rb +93 -56
  131. data/lib/active_support/core_ext/string/behavior.rb +8 -0
  132. data/lib/active_support/core_ext/string/conversions.rb +57 -16
  133. data/lib/active_support/core_ext/string/exclude.rb +13 -0
  134. data/lib/active_support/core_ext/string/filters.rb +151 -0
  135. data/lib/active_support/core_ext/string/indent.rb +45 -0
  136. data/lib/active_support/core_ext/string/inflections.rb +297 -54
  137. data/lib/active_support/core_ext/string/inquiry.rb +16 -0
  138. data/lib/active_support/core_ext/string/multibyte.rb +67 -0
  139. data/lib/active_support/core_ext/string/output_safety.rb +235 -0
  140. data/lib/active_support/core_ext/string/starts_ends_with.rb +4 -18
  141. data/lib/active_support/core_ext/string/strip.rb +27 -0
  142. data/lib/active_support/core_ext/string/zones.rb +16 -0
  143. data/lib/active_support/core_ext/string.rb +14 -10
  144. data/lib/active_support/core_ext/symbol/starts_ends_with.rb +6 -0
  145. data/lib/active_support/core_ext/symbol.rb +3 -0
  146. data/lib/active_support/core_ext/thread/backtrace/location.rb +7 -0
  147. data/lib/active_support/core_ext/time/acts_like.rb +10 -0
  148. data/lib/active_support/core_ext/time/calculations.rb +358 -153
  149. data/lib/active_support/core_ext/time/compatibility.rb +15 -0
  150. data/lib/active_support/core_ext/time/conversions.rb +69 -30
  151. data/lib/active_support/core_ext/time/zones.rb +97 -0
  152. data/lib/active_support/core_ext/time.rb +6 -6
  153. data/lib/active_support/core_ext.rb +5 -1
  154. data/lib/active_support/current_attributes/test_helper.rb +13 -0
  155. data/lib/active_support/current_attributes.rb +243 -0
  156. data/lib/active_support/deep_mergeable.rb +53 -0
  157. data/lib/active_support/delegation.rb +183 -0
  158. data/lib/active_support/dependencies/autoload.rb +72 -0
  159. data/lib/active_support/dependencies/interlock.rb +55 -0
  160. data/lib/active_support/dependencies/require_dependency.rb +28 -0
  161. data/lib/active_support/dependencies.rb +84 -222
  162. data/lib/active_support/deprecation/behaviors.rb +148 -0
  163. data/lib/active_support/deprecation/constant_accessor.rb +74 -0
  164. data/lib/active_support/deprecation/deprecators.rb +104 -0
  165. data/lib/active_support/deprecation/disallowed.rb +54 -0
  166. data/lib/active_support/deprecation/method_wrappers.rb +68 -0
  167. data/lib/active_support/deprecation/proxy_wrappers.rb +189 -0
  168. data/lib/active_support/deprecation/reporting.rb +162 -0
  169. data/lib/active_support/deprecation.rb +81 -0
  170. data/lib/active_support/deprecator.rb +7 -0
  171. data/lib/active_support/descendants_tracker.rb +112 -0
  172. data/lib/active_support/digest.rb +22 -0
  173. data/lib/active_support/duration/iso8601_parser.rb +123 -0
  174. data/lib/active_support/duration/iso8601_serializer.rb +64 -0
  175. data/lib/active_support/duration.rb +524 -0
  176. data/lib/active_support/editor.rb +70 -0
  177. data/lib/active_support/encrypted_configuration.rb +126 -0
  178. data/lib/active_support/encrypted_file.rb +133 -0
  179. data/lib/active_support/environment_inquirer.rb +40 -0
  180. data/lib/active_support/error_reporter/test_helper.rb +15 -0
  181. data/lib/active_support/error_reporter.rb +318 -0
  182. data/lib/active_support/event_reporter/test_helper.rb +32 -0
  183. data/lib/active_support/event_reporter.rb +592 -0
  184. data/lib/active_support/evented_file_update_checker.rb +185 -0
  185. data/lib/active_support/execution_context/test_helper.rb +13 -0
  186. data/lib/active_support/execution_context.rb +110 -0
  187. data/lib/active_support/execution_wrapper.rb +150 -0
  188. data/lib/active_support/executor/test_helper.rb +7 -0
  189. data/lib/active_support/executor.rb +8 -0
  190. data/lib/active_support/file_update_checker.rb +166 -0
  191. data/lib/active_support/fork_tracker.rb +43 -0
  192. data/lib/active_support/gem_version.rb +17 -0
  193. data/lib/active_support/gzip.rb +41 -0
  194. data/lib/active_support/hash_with_indifferent_access.rb +464 -0
  195. data/lib/active_support/html_safe_translation.rb +56 -0
  196. data/lib/active_support/i18n.rb +17 -0
  197. data/lib/active_support/i18n_railtie.rb +140 -0
  198. data/lib/active_support/inflections.rb +68 -49
  199. data/lib/active_support/inflector/inflections.rb +290 -0
  200. data/lib/active_support/inflector/methods.rb +387 -0
  201. data/lib/active_support/inflector/transliterate.rb +147 -0
  202. data/lib/active_support/inflector.rb +7 -164
  203. data/lib/active_support/isolated_execution_state.rb +76 -0
  204. data/lib/active_support/json/decoding.rb +78 -0
  205. data/lib/active_support/json/encoding.rb +256 -0
  206. data/lib/active_support/json.rb +4 -0
  207. data/lib/active_support/key_generator.rb +66 -0
  208. data/lib/active_support/lazy_load_hooks.rb +107 -0
  209. data/lib/active_support/locale/en.rb +33 -0
  210. data/lib/active_support/locale/en.yml +141 -0
  211. data/lib/active_support/log_subscriber/test_helper.rb +106 -0
  212. data/lib/active_support/log_subscriber.rb +188 -0
  213. data/lib/active_support/logger.rb +55 -0
  214. data/lib/active_support/logger_silence.rb +21 -0
  215. data/lib/active_support/logger_thread_safe_level.rb +50 -0
  216. data/lib/active_support/message_encryptor.rb +374 -0
  217. data/lib/active_support/message_encryptors.rb +193 -0
  218. data/lib/active_support/message_pack/cache_serializer.rb +23 -0
  219. data/lib/active_support/message_pack/extensions.rb +310 -0
  220. data/lib/active_support/message_pack/serializer.rb +63 -0
  221. data/lib/active_support/message_pack.rb +50 -0
  222. data/lib/active_support/message_verifier.rb +377 -0
  223. data/lib/active_support/message_verifiers.rb +189 -0
  224. data/lib/active_support/messages/codec.rb +65 -0
  225. data/lib/active_support/messages/metadata.rb +146 -0
  226. data/lib/active_support/messages/rotation_configuration.rb +23 -0
  227. data/lib/active_support/messages/rotation_coordinator.rb +102 -0
  228. data/lib/active_support/messages/rotator.rb +69 -0
  229. data/lib/active_support/messages/serializer_with_fallback.rb +158 -0
  230. data/lib/active_support/multibyte/chars.rb +188 -0
  231. data/lib/active_support/multibyte/unicode.rb +42 -0
  232. data/lib/active_support/multibyte.rb +27 -0
  233. data/lib/active_support/notifications/fanout.rb +467 -0
  234. data/lib/active_support/notifications/instrumenter.rb +240 -0
  235. data/lib/active_support/notifications.rb +281 -0
  236. data/lib/active_support/number_helper/number_converter.rb +190 -0
  237. data/lib/active_support/number_helper/number_to_currency_converter.rb +46 -0
  238. data/lib/active_support/number_helper/number_to_delimited_converter.rb +30 -0
  239. data/lib/active_support/number_helper/number_to_human_converter.rb +69 -0
  240. data/lib/active_support/number_helper/number_to_human_size_converter.rb +60 -0
  241. data/lib/active_support/number_helper/number_to_percentage_converter.rb +16 -0
  242. data/lib/active_support/number_helper/number_to_phone_converter.rb +60 -0
  243. data/lib/active_support/number_helper/number_to_rounded_converter.rb +59 -0
  244. data/lib/active_support/number_helper/rounding_helper.rb +46 -0
  245. data/lib/active_support/number_helper.rb +479 -0
  246. data/lib/active_support/option_merger.rb +38 -0
  247. data/lib/active_support/ordered_hash.rb +50 -0
  248. data/lib/active_support/ordered_options.rb +141 -25
  249. data/lib/active_support/parameter_filter.rb +157 -0
  250. data/lib/active_support/rails.rb +26 -0
  251. data/lib/active_support/railtie.rb +180 -0
  252. data/lib/active_support/reloader.rb +138 -0
  253. data/lib/active_support/rescuable.rb +176 -0
  254. data/lib/active_support/secure_compare_rotator.rb +58 -0
  255. data/lib/active_support/security_utils.rb +38 -0
  256. data/lib/active_support/string_inquirer.rb +35 -0
  257. data/lib/active_support/structured_event_subscriber.rb +99 -0
  258. data/lib/active_support/subscriber.rb +141 -0
  259. data/lib/active_support/syntax_error_proxy.rb +67 -0
  260. data/lib/active_support/tagged_logging.rb +157 -0
  261. data/lib/active_support/test_case.rb +365 -0
  262. data/lib/active_support/testing/assertions.rb +369 -0
  263. data/lib/active_support/testing/autorun.rb +10 -0
  264. data/lib/active_support/testing/constant_lookup.rb +51 -0
  265. data/lib/active_support/testing/constant_stubbing.rb +54 -0
  266. data/lib/active_support/testing/declarative.rb +28 -0
  267. data/lib/active_support/testing/deprecation.rb +82 -0
  268. data/lib/active_support/testing/error_reporter_assertions.rb +124 -0
  269. data/lib/active_support/testing/event_reporter_assertions.rb +227 -0
  270. data/lib/active_support/testing/file_fixtures.rb +38 -0
  271. data/lib/active_support/testing/isolation.rb +121 -0
  272. data/lib/active_support/testing/method_call_assertions.rb +69 -0
  273. data/lib/active_support/testing/notification_assertions.rb +92 -0
  274. data/lib/active_support/testing/parallelization/server.rb +98 -0
  275. data/lib/active_support/testing/parallelization/worker.rb +107 -0
  276. data/lib/active_support/testing/parallelization.rb +79 -0
  277. data/lib/active_support/testing/parallelize_executor.rb +81 -0
  278. data/lib/active_support/testing/setup_and_teardown.rb +57 -0
  279. data/lib/active_support/testing/stream.rb +41 -0
  280. data/lib/active_support/testing/tagged_logging.rb +27 -0
  281. data/lib/active_support/testing/tests_without_assertions.rb +19 -0
  282. data/lib/active_support/testing/time_helpers.rb +273 -0
  283. data/lib/active_support/time.rb +20 -0
  284. data/lib/active_support/time_with_zone.rb +613 -0
  285. data/lib/active_support/values/time_zone.rb +599 -158
  286. data/lib/active_support/version.rb +7 -6
  287. data/lib/active_support/xml_mini/jdom.rb +175 -0
  288. data/lib/active_support/xml_mini/libxml.rb +80 -0
  289. data/lib/active_support/xml_mini/libxmlsax.rb +83 -0
  290. data/lib/active_support/xml_mini/nokogiri.rb +83 -0
  291. data/lib/active_support/xml_mini/nokogirisax.rb +86 -0
  292. data/lib/active_support/xml_mini/rexml.rb +137 -0
  293. data/lib/active_support/xml_mini.rb +212 -0
  294. data/lib/active_support.rb +122 -10
  295. metadata +524 -93
  296. data/CHANGELOG +0 -283
  297. data/lib/active_support/binding_of_caller.rb +0 -84
  298. data/lib/active_support/breakpoint.rb +0 -523
  299. data/lib/active_support/class_attribute_accessors.rb +0 -57
  300. data/lib/active_support/class_inheritable_attributes.rb +0 -117
  301. data/lib/active_support/clean_logger.rb +0 -36
  302. data/lib/active_support/core_ext/blank.rb +0 -38
  303. data/lib/active_support/core_ext/cgi/escape_skipping_slashes.rb +0 -14
  304. data/lib/active_support/core_ext/cgi.rb +0 -5
  305. data/lib/active_support/core_ext/exception.rb +0 -29
  306. data/lib/active_support/core_ext/integer/even_odd.rb +0 -24
  307. data/lib/active_support/core_ext/object_and_class.rb +0 -44
  308. data/lib/active_support/module_attribute_accessors.rb +0 -57
  309. data/lib/active_support/whiny_nil.rb +0 -38
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "zlib"
4
+ require "stringio"
5
+
6
+ module ActiveSupport
7
+ # = Active Support \Gzip
8
+ #
9
+ # A convenient wrapper for the zlib standard library that allows
10
+ # compression/decompression of strings with gzip.
11
+ #
12
+ # gzip = ActiveSupport::Gzip.compress('compress me!')
13
+ # # => "\x1F\x8B\b\x00o\x8D\xCDO\x00\x03K\xCE\xCF-(J-.V\xC8MU\x04\x00R>n\x83\f\x00\x00\x00"
14
+ #
15
+ # ActiveSupport::Gzip.decompress(gzip)
16
+ # # => "compress me!"
17
+ module Gzip
18
+ class Stream < StringIO
19
+ def initialize(*)
20
+ super
21
+ set_encoding "BINARY"
22
+ end
23
+ def close; rewind; end
24
+ end
25
+
26
+ # Decompresses a gzipped string.
27
+ def self.decompress(source)
28
+ Zlib::GzipReader.wrap(StringIO.new(source), &:read)
29
+ end
30
+
31
+ # Compresses a string using gzip.
32
+ def self.compress(source, level = Zlib::DEFAULT_COMPRESSION, strategy = Zlib::DEFAULT_STRATEGY)
33
+ output = Stream.new
34
+ gz = Zlib::GzipWriter.new(output, level, strategy)
35
+ gz.mtime = 0
36
+ gz.write(source)
37
+ gz.close
38
+ output.string
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,464 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/hash/keys"
4
+ require "active_support/core_ext/hash/reverse_merge"
5
+ require "active_support/core_ext/hash/except"
6
+ require "active_support/core_ext/hash/slice"
7
+
8
+ module ActiveSupport
9
+ # = \Hash With Indifferent Access
10
+ #
11
+ # Implements a hash where keys <tt>:foo</tt> and <tt>"foo"</tt> are considered
12
+ # to be the same.
13
+ #
14
+ # rgb = ActiveSupport::HashWithIndifferentAccess.new
15
+ #
16
+ # rgb[:black] = '#000000'
17
+ # rgb[:black] # => '#000000'
18
+ # rgb['black'] # => '#000000'
19
+ #
20
+ # rgb['white'] = '#FFFFFF'
21
+ # rgb[:white] # => '#FFFFFF'
22
+ # rgb['white'] # => '#FFFFFF'
23
+ #
24
+ # Internally symbols are mapped to strings when used as keys in the entire
25
+ # writing interface (calling <tt>[]=</tt>, <tt>merge</tt>, etc). This
26
+ # mapping belongs to the public interface. For example, given:
27
+ #
28
+ # hash = ActiveSupport::HashWithIndifferentAccess.new(a: 1)
29
+ #
30
+ # You are guaranteed that the key is returned as a string:
31
+ #
32
+ # hash.keys # => ["a"]
33
+ #
34
+ # Technically other types of keys are accepted:
35
+ #
36
+ # hash = ActiveSupport::HashWithIndifferentAccess.new(a: 1)
37
+ # hash[0] = 0
38
+ # hash # => {"a"=>1, 0=>0}
39
+ #
40
+ # but this class is intended for use cases where strings or symbols are the
41
+ # expected keys and it is convenient to understand both as the same. For
42
+ # example the +params+ hash in Ruby on \Rails.
43
+ #
44
+ # Note that core extensions define <tt>Hash#with_indifferent_access</tt>:
45
+ #
46
+ # rgb = { black: '#000000', white: '#FFFFFF' }.with_indifferent_access
47
+ #
48
+ # which may be handy.
49
+ #
50
+ # To access this class outside of \Rails, require the core extension with:
51
+ #
52
+ # require "active_support/core_ext/hash/indifferent_access"
53
+ #
54
+ # which will, in turn, require this file.
55
+ class HashWithIndifferentAccess < Hash
56
+ # Returns +true+ so that <tt>Array#extract_options!</tt> finds members of
57
+ # this class.
58
+ def extractable_options?
59
+ true
60
+ end
61
+
62
+ def with_indifferent_access
63
+ dup
64
+ end
65
+
66
+ def nested_under_indifferent_access
67
+ self
68
+ end
69
+
70
+ def initialize(constructor = nil)
71
+ if constructor.nil?
72
+ super()
73
+ elsif constructor.respond_to?(:to_hash)
74
+ super()
75
+ update(constructor)
76
+
77
+ hash = constructor.is_a?(Hash) ? constructor : constructor.to_hash
78
+ self.default = hash.default if hash.default
79
+ self.default_proc = hash.default_proc if hash.default_proc
80
+ else
81
+ super(constructor)
82
+ end
83
+ end
84
+
85
+ def self.[](*args)
86
+ new.merge!(Hash[*args])
87
+ end
88
+
89
+ alias_method :regular_writer, :[]= unless method_defined?(:regular_writer)
90
+ alias_method :regular_update, :update unless method_defined?(:regular_update)
91
+
92
+ # Assigns a new value to the hash:
93
+ #
94
+ # hash = ActiveSupport::HashWithIndifferentAccess.new
95
+ # hash[:key] = 'value'
96
+ #
97
+ # This value can be later fetched using either +:key+ or <tt>'key'</tt>.
98
+ #
99
+ # If the value is a Hash or contains one or multiple Hashes, they will be
100
+ # converted to +HashWithIndifferentAccess+.
101
+ def []=(key, value)
102
+ regular_writer(convert_key(key), convert_value(value, conversion: :assignment))
103
+ end
104
+
105
+ # Assigns a new value to the hash:
106
+ #
107
+ # hash = ActiveSupport::HashWithIndifferentAccess.new
108
+ # hash[:key] = 'value'
109
+ #
110
+ # This value can be later fetched using either +:key+ or <tt>'key'</tt>.
111
+ #
112
+ # If the value is a Hash or contains one or multiple Hashes, they will be
113
+ # converted to +HashWithIndifferentAccess+. unless `convert_value: false`
114
+ # is set.
115
+ def store(key, value, convert_value: true)
116
+ value = convert_value(value, conversion: :assignment) if convert_value
117
+ regular_writer(convert_key(key), value)
118
+ end
119
+
120
+ # Updates the receiver in-place, merging in the hashes passed as arguments:
121
+ #
122
+ # hash_1 = ActiveSupport::HashWithIndifferentAccess.new
123
+ # hash_1[:key] = 'value'
124
+ #
125
+ # hash_2 = ActiveSupport::HashWithIndifferentAccess.new
126
+ # hash_2[:key] = 'New Value!'
127
+ #
128
+ # hash_1.update(hash_2) # => {"key"=>"New Value!"}
129
+ #
130
+ # hash = ActiveSupport::HashWithIndifferentAccess.new
131
+ # hash.update({ "a" => 1 }, { "b" => 2 }) # => { "a" => 1, "b" => 2 }
132
+ #
133
+ # The arguments can be either an
134
+ # +ActiveSupport::HashWithIndifferentAccess+ or a regular +Hash+.
135
+ # In either case the merge respects the semantics of indifferent access.
136
+ #
137
+ # If the argument is a regular hash with keys +:key+ and <tt>"key"</tt> only one
138
+ # of the values end up in the receiver, but which one is unspecified.
139
+ #
140
+ # When given a block, the value for duplicated keys will be determined
141
+ # by the result of invoking the block with the duplicated key, the value
142
+ # in the receiver, and the value in +other_hash+. The rules for duplicated
143
+ # keys follow the semantics of indifferent access:
144
+ #
145
+ # hash_1[:key] = 10
146
+ # hash_2['key'] = 12
147
+ # hash_1.update(hash_2) { |key, old, new| old + new } # => {"key"=>22}
148
+ def update(*other_hashes, &block)
149
+ if other_hashes.size == 1
150
+ update_with_single_argument(other_hashes.first, block)
151
+ else
152
+ other_hashes.each do |other_hash|
153
+ update_with_single_argument(other_hash, block)
154
+ end
155
+ end
156
+ self
157
+ end
158
+
159
+ alias_method :merge!, :update
160
+
161
+ # Checks the hash for a key matching the argument passed in:
162
+ #
163
+ # hash = ActiveSupport::HashWithIndifferentAccess.new
164
+ # hash['key'] = 'value'
165
+ # hash.key?(:key) # => true
166
+ # hash.key?('key') # => true
167
+ def key?(key)
168
+ super(convert_key(key))
169
+ end
170
+
171
+ alias_method :include?, :key?
172
+ alias_method :has_key?, :key?
173
+ alias_method :member?, :key?
174
+
175
+ # Same as <tt>Hash#[]</tt> where the key passed as argument can be
176
+ # either a string or a symbol:
177
+ #
178
+ # counters = ActiveSupport::HashWithIndifferentAccess.new
179
+ # counters[:foo] = 1
180
+ #
181
+ # counters['foo'] # => 1
182
+ # counters[:foo] # => 1
183
+ # counters[:zoo] # => nil
184
+ def [](key)
185
+ super(convert_key(key))
186
+ end
187
+
188
+ # Same as <tt>Hash#assoc</tt> where the key passed as argument can be
189
+ # either a string or a symbol:
190
+ #
191
+ # counters = ActiveSupport::HashWithIndifferentAccess.new
192
+ # counters[:foo] = 1
193
+ #
194
+ # counters.assoc('foo') # => ["foo", 1]
195
+ # counters.assoc(:foo) # => ["foo", 1]
196
+ # counters.assoc(:zoo) # => nil
197
+ def assoc(key)
198
+ super(convert_key(key))
199
+ end
200
+
201
+ # Same as <tt>Hash#fetch</tt> where the key passed as argument can be
202
+ # either a string or a symbol:
203
+ #
204
+ # counters = ActiveSupport::HashWithIndifferentAccess.new
205
+ # counters[:foo] = 1
206
+ #
207
+ # counters.fetch('foo') # => 1
208
+ # counters.fetch(:bar, 0) # => 0
209
+ # counters.fetch(:bar) { |key| 0 } # => 0
210
+ # counters.fetch(:zoo) # => KeyError: key not found: "zoo"
211
+ def fetch(key, *extras)
212
+ super(convert_key(key), *extras)
213
+ end
214
+
215
+ # Same as <tt>Hash#dig</tt> where the key passed as argument can be
216
+ # either a string or a symbol:
217
+ #
218
+ # counters = ActiveSupport::HashWithIndifferentAccess.new
219
+ # counters[:foo] = { bar: 1 }
220
+ #
221
+ # counters.dig('foo', 'bar') # => 1
222
+ # counters.dig(:foo, :bar) # => 1
223
+ # counters.dig(:zoo) # => nil
224
+ def dig(*args)
225
+ args[0] = convert_key(args[0]) if args.size > 0
226
+ super(*args)
227
+ end
228
+
229
+ # Same as <tt>Hash#default</tt> where the key passed as argument can be
230
+ # either a string or a symbol:
231
+ #
232
+ # hash = ActiveSupport::HashWithIndifferentAccess.new(1)
233
+ # hash.default # => 1
234
+ #
235
+ # hash = ActiveSupport::HashWithIndifferentAccess.new { |hash, key| key }
236
+ # hash.default # => nil
237
+ # hash.default('foo') # => 'foo'
238
+ # hash.default(:foo) # => 'foo'
239
+ def default(key = (no_key = true))
240
+ if no_key
241
+ super()
242
+ else
243
+ super(convert_key(key))
244
+ end
245
+ end
246
+
247
+ # Returns an array of the values at the specified indices:
248
+ #
249
+ # hash = ActiveSupport::HashWithIndifferentAccess.new
250
+ # hash[:a] = 'x'
251
+ # hash[:b] = 'y'
252
+ # hash.values_at('a', 'b') # => ["x", "y"]
253
+ def values_at(*keys)
254
+ keys.map! { |key| convert_key(key) }
255
+ super
256
+ end
257
+
258
+ # Returns an array of the values at the specified indices, but also
259
+ # raises an exception when one of the keys can't be found.
260
+ #
261
+ # hash = ActiveSupport::HashWithIndifferentAccess.new
262
+ # hash[:a] = 'x'
263
+ # hash[:b] = 'y'
264
+ # hash.fetch_values('a', 'b') # => ["x", "y"]
265
+ # hash.fetch_values('a', 'c') { |key| 'z' } # => ["x", "z"]
266
+ # hash.fetch_values('a', 'c') # => KeyError: key not found: "c"
267
+ def fetch_values(*indices, &block)
268
+ indices.map! { |key| convert_key(key) }
269
+ super
270
+ end
271
+
272
+ # Returns a shallow copy of the hash.
273
+ #
274
+ # hash = ActiveSupport::HashWithIndifferentAccess.new({ a: { b: 'b' } })
275
+ # dup = hash.dup
276
+ # dup[:a][:c] = 'c'
277
+ #
278
+ # hash[:a][:c] # => "c"
279
+ # dup[:a][:c] # => "c"
280
+ def dup
281
+ copy_defaults(self.class.new(self))
282
+ end
283
+
284
+ # This method has the same semantics of +update+, except it does not
285
+ # modify the receiver but rather returns a new hash with indifferent
286
+ # access with the result of the merge.
287
+ def merge(*hashes, &block)
288
+ dup.update(*hashes, &block)
289
+ end
290
+
291
+ # Like +merge+ but the other way around: Merges the receiver into the
292
+ # argument and returns a new hash with indifferent access as result:
293
+ #
294
+ # hash = ActiveSupport::HashWithIndifferentAccess.new
295
+ # hash['a'] = nil
296
+ # hash.reverse_merge(a: 0, b: 1) # => {"a"=>nil, "b"=>1}
297
+ def reverse_merge(other_hash)
298
+ super(cast(other_hash))
299
+ end
300
+ alias_method :with_defaults, :reverse_merge
301
+
302
+ # Same semantics as +reverse_merge+ but modifies the receiver in-place.
303
+ def reverse_merge!(other_hash)
304
+ super(cast(other_hash))
305
+ end
306
+ alias_method :with_defaults!, :reverse_merge!
307
+
308
+ # Replaces the contents of this hash with other_hash.
309
+ #
310
+ # h = { "a" => 100, "b" => 200 }
311
+ # h.replace({ "c" => 300, "d" => 400 }) # => {"c"=>300, "d"=>400}
312
+ def replace(other_hash)
313
+ super(cast(other_hash))
314
+ end
315
+
316
+ # Removes the specified key from the hash.
317
+ def delete(key)
318
+ super(convert_key(key))
319
+ end
320
+
321
+ # Returns a hash with indifferent access that includes everything except given keys.
322
+ # hash = { a: "x", b: "y", c: 10 }.with_indifferent_access
323
+ # hash.except(:a, "b") # => {c: 10}.with_indifferent_access
324
+ # hash # => { a: "x", b: "y", c: 10 }.with_indifferent_access
325
+ def except(*keys)
326
+ dup.except!(*keys)
327
+ end
328
+ alias_method :without, :except
329
+
330
+ undef :symbolize_keys!
331
+ undef :deep_symbolize_keys!
332
+ def symbolize_keys; to_hash.symbolize_keys! end
333
+ alias_method :to_options, :symbolize_keys
334
+ def deep_symbolize_keys; to_hash.deep_symbolize_keys! end
335
+ def to_options!; self end
336
+
337
+ def select(*args, &block)
338
+ return to_enum(:select) unless block_given?
339
+ dup.tap { |hash| hash.select!(*args, &block) }
340
+ end
341
+
342
+ def reject(*args, &block)
343
+ return to_enum(:reject) unless block_given?
344
+ dup.tap { |hash| hash.reject!(*args, &block) }
345
+ end
346
+
347
+ def transform_values(&block)
348
+ return to_enum(:transform_values) unless block_given?
349
+ dup.tap { |hash| hash.transform_values!(&block) }
350
+ end
351
+
352
+ NOT_GIVEN = Object.new # :nodoc:
353
+
354
+ def transform_keys(hash = NOT_GIVEN, &block)
355
+ if NOT_GIVEN.equal?(hash)
356
+ if block_given?
357
+ self.class.new(super(&block))
358
+ else
359
+ to_enum(:transform_keys)
360
+ end
361
+ else
362
+ self.class.new(super)
363
+ end
364
+ end
365
+
366
+ def transform_keys!(hash = NOT_GIVEN, &block)
367
+ if NOT_GIVEN.equal?(hash)
368
+ if block_given?
369
+ replace(copy_defaults(transform_keys(&block)))
370
+ else
371
+ return to_enum(:transform_keys!)
372
+ end
373
+ else
374
+ replace(copy_defaults(transform_keys(hash, &block)))
375
+ end
376
+
377
+ self
378
+ end
379
+
380
+ def slice(*keys)
381
+ keys.map! { |key| convert_key(key) }
382
+ self.class.new(super)
383
+ end
384
+
385
+ def slice!(*keys)
386
+ keys.map! { |key| convert_key(key) }
387
+ super
388
+ end
389
+
390
+ def compact
391
+ dup.tap(&:compact!)
392
+ end
393
+
394
+ # Convert to a regular hash with string keys.
395
+ def to_hash
396
+ copy = Hash[self]
397
+ copy.transform_values! { |v| convert_value_to_hash(v) }
398
+ copy_defaults(copy)
399
+ end
400
+
401
+ def to_proc
402
+ proc { |key| self[key] }
403
+ end
404
+
405
+ private
406
+ def cast(other)
407
+ self.class === other ? other : self.class.new(other)
408
+ end
409
+
410
+ def convert_key(key)
411
+ Symbol === key ? key.name : key
412
+ end
413
+
414
+ def convert_value(value, conversion: nil)
415
+ if value.is_a? Hash
416
+ value.nested_under_indifferent_access
417
+ elsif value.is_a?(Array)
418
+ if conversion != :assignment || value.frozen?
419
+ value = value.dup
420
+ end
421
+ value.map! { |e| convert_value(e, conversion: conversion) }
422
+ else
423
+ value
424
+ end
425
+ end
426
+
427
+ def convert_value_to_hash(value)
428
+ if value.is_a? Hash
429
+ value.to_hash
430
+ elsif value.is_a?(Array)
431
+ value.map { |e| convert_value_to_hash(e) }
432
+ else
433
+ value
434
+ end
435
+ end
436
+
437
+
438
+ def copy_defaults(target)
439
+ if default_proc
440
+ target.default_proc = default_proc.dup
441
+ else
442
+ target.default = default
443
+ end
444
+ target
445
+ end
446
+
447
+ def update_with_single_argument(other_hash, block)
448
+ if other_hash.is_a? HashWithIndifferentAccess
449
+ regular_update(other_hash, &block)
450
+ else
451
+ other_hash.to_hash.each_pair do |key, value|
452
+ if block && key?(key)
453
+ value = block.call(convert_key(key), self[key], value)
454
+ end
455
+ regular_writer(convert_key(key), convert_value(value))
456
+ end
457
+ end
458
+ end
459
+ end
460
+ end
461
+
462
+ # :stopdoc:
463
+
464
+ HashWithIndifferentAccess = ActiveSupport::HashWithIndifferentAccess
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveSupport
4
+ module HtmlSafeTranslation # :nodoc:
5
+ extend self
6
+
7
+ def translate(key, **options)
8
+ if html_safe_translation_key?(key)
9
+ html_safe_options = html_escape_translation_options(options)
10
+
11
+ exception = false
12
+
13
+ exception_handler = ->(*args) do
14
+ exception = true
15
+ I18n.exception_handler.call(*args)
16
+ end
17
+
18
+ translation = I18n.translate(key, **html_safe_options, exception_handler: exception_handler)
19
+
20
+ if exception
21
+ translation
22
+ else
23
+ html_safe_translation(translation)
24
+ end
25
+ else
26
+ I18n.translate(key, **options)
27
+ end
28
+ end
29
+
30
+ def html_safe_translation_key?(key)
31
+ /(?:_|\b)html\z/.match?(key)
32
+ end
33
+
34
+ private
35
+ def html_escape_translation_options(options)
36
+ options.each do |name, value|
37
+ unless i18n_option?(name) || (name == :count && value.is_a?(Numeric))
38
+ options[name] = ERB::Util.html_escape(value.to_s)
39
+ end
40
+ end
41
+ end
42
+
43
+ def i18n_option?(name)
44
+ (@i18n_option_names ||= I18n::RESERVED_KEYS.to_set).include?(name)
45
+ end
46
+
47
+
48
+ def html_safe_translation(translation)
49
+ if translation.respond_to?(:map)
50
+ translation.map { |element| element.respond_to?(:html_safe) ? element.html_safe : element }
51
+ else
52
+ translation.respond_to?(:html_safe) ? translation.html_safe : translation
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/hash/deep_merge"
4
+ require "active_support/core_ext/hash/except"
5
+ require "active_support/core_ext/hash/slice"
6
+ begin
7
+ require "i18n"
8
+ require "i18n/backend/fallbacks"
9
+ rescue LoadError => e
10
+ warn "The i18n gem is not available. Please add it to your Gemfile and run bundle install"
11
+ raise e
12
+ end
13
+ require "active_support/lazy_load_hooks"
14
+
15
+ ActiveSupport.run_load_hooks(:i18n)
16
+ I18n.load_path << File.expand_path("locale/en.yml", __dir__)
17
+ I18n.load_path << File.expand_path("locale/en.rb", __dir__)