activesupport 4.0.12 → 7.0.2.4

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 (295) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +249 -501
  3. data/MIT-LICENSE +2 -2
  4. data/README.rdoc +10 -5
  5. data/lib/active_support/actionable_error.rb +48 -0
  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 +41 -13
  9. data/lib/active_support/benchmarkable.rb +7 -15
  10. data/lib/active_support/builder.rb +3 -1
  11. data/lib/active_support/cache/file_store.rb +96 -74
  12. data/lib/active_support/cache/mem_cache_store.rb +211 -103
  13. data/lib/active_support/cache/memory_store.rb +90 -58
  14. data/lib/active_support/cache/null_store.rb +19 -7
  15. data/lib/active_support/cache/redis_cache_store.rb +468 -0
  16. data/lib/active_support/cache/strategy/local_cache.rb +86 -83
  17. data/lib/active_support/cache/strategy/local_cache_middleware.rb +45 -0
  18. data/lib/active_support/cache.rb +580 -241
  19. data/lib/active_support/callbacks.rb +812 -425
  20. data/lib/active_support/code_generator.rb +65 -0
  21. data/lib/active_support/concern.rb +103 -14
  22. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +33 -0
  23. data/lib/active_support/concurrency/share_lock.rb +226 -0
  24. data/lib/active_support/configurable.rb +21 -19
  25. data/lib/active_support/configuration_file.rb +51 -0
  26. data/lib/active_support/core_ext/array/access.rb +47 -1
  27. data/lib/active_support/core_ext/array/conversions.rb +35 -44
  28. data/lib/active_support/core_ext/array/deprecated_conversions.rb +25 -0
  29. data/lib/active_support/core_ext/array/extract.rb +21 -0
  30. data/lib/active_support/core_ext/array/extract_options.rb +2 -0
  31. data/lib/active_support/core_ext/array/grouping.rb +26 -16
  32. data/lib/active_support/core_ext/array/inquiry.rb +19 -0
  33. data/lib/active_support/core_ext/array/wrap.rb +7 -4
  34. data/lib/active_support/core_ext/array.rb +10 -7
  35. data/lib/active_support/core_ext/benchmark.rb +5 -3
  36. data/lib/active_support/core_ext/big_decimal/conversions.rb +9 -26
  37. data/lib/active_support/core_ext/big_decimal.rb +3 -1
  38. data/lib/active_support/core_ext/class/attribute.rb +52 -49
  39. data/lib/active_support/core_ext/class/attribute_accessors.rb +5 -169
  40. data/lib/active_support/core_ext/class/subclasses.rb +25 -26
  41. data/lib/active_support/core_ext/class.rb +4 -4
  42. data/lib/active_support/core_ext/date/acts_like.rb +3 -1
  43. data/lib/active_support/core_ext/date/blank.rb +14 -0
  44. data/lib/active_support/core_ext/date/calculations.rb +31 -18
  45. data/lib/active_support/core_ext/date/conversions.rb +43 -32
  46. data/lib/active_support/core_ext/date/deprecated_conversions.rb +26 -0
  47. data/lib/active_support/core_ext/date/zones.rb +5 -34
  48. data/lib/active_support/core_ext/date.rb +7 -4
  49. data/lib/active_support/core_ext/date_and_time/calculations.rb +198 -66
  50. data/lib/active_support/core_ext/date_and_time/compatibility.rb +31 -0
  51. data/lib/active_support/core_ext/date_and_time/zones.rb +40 -0
  52. data/lib/active_support/core_ext/date_time/acts_like.rb +4 -2
  53. data/lib/active_support/core_ext/date_time/blank.rb +14 -0
  54. data/lib/active_support/core_ext/date_time/calculations.rb +79 -38
  55. data/lib/active_support/core_ext/date_time/compatibility.rb +18 -0
  56. data/lib/active_support/core_ext/date_time/conversions.rb +31 -26
  57. data/lib/active_support/core_ext/date_time/deprecated_conversions.rb +22 -0
  58. data/lib/active_support/core_ext/date_time.rb +8 -4
  59. data/lib/active_support/core_ext/digest/uuid.rb +79 -0
  60. data/lib/active_support/core_ext/digest.rb +3 -0
  61. data/lib/active_support/core_ext/enumerable.rb +249 -17
  62. data/lib/active_support/core_ext/file/atomic.rb +41 -32
  63. data/lib/active_support/core_ext/file.rb +3 -1
  64. data/lib/active_support/core_ext/hash/conversions.rb +71 -49
  65. data/lib/active_support/core_ext/hash/deep_merge.rb +9 -13
  66. data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
  67. data/lib/active_support/core_ext/hash/except.rb +14 -5
  68. data/lib/active_support/core_ext/hash/indifferent_access.rb +5 -3
  69. data/lib/active_support/core_ext/hash/keys.rb +39 -56
  70. data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
  71. data/lib/active_support/core_ext/hash/slice.rb +8 -23
  72. data/lib/active_support/core_ext/hash.rb +10 -8
  73. data/lib/active_support/core_ext/integer/inflections.rb +3 -1
  74. data/lib/active_support/core_ext/integer/multiple.rb +3 -1
  75. data/lib/active_support/core_ext/integer/time.rb +11 -33
  76. data/lib/active_support/core_ext/integer.rb +5 -3
  77. data/lib/active_support/core_ext/kernel/concern.rb +14 -0
  78. data/lib/active_support/core_ext/kernel/reporting.rb +9 -78
  79. data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
  80. data/lib/active_support/core_ext/kernel.rb +5 -4
  81. data/lib/active_support/core_ext/load_error.rb +5 -21
  82. data/lib/active_support/core_ext/module/aliasing.rb +6 -44
  83. data/lib/active_support/core_ext/module/anonymous.rb +12 -1
  84. data/lib/active_support/core_ext/module/attr_internal.rb +8 -8
  85. data/lib/active_support/core_ext/module/attribute_accessors.rb +186 -44
  86. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +157 -0
  87. data/lib/active_support/core_ext/module/concerning.rb +140 -0
  88. data/lib/active_support/core_ext/module/delegation.rb +172 -45
  89. data/lib/active_support/core_ext/module/deprecation.rb +3 -3
  90. data/lib/active_support/core_ext/module/introspection.rb +23 -38
  91. data/lib/active_support/core_ext/module/redefine_method.rb +40 -0
  92. data/lib/active_support/core_ext/module/remove_method.rb +8 -3
  93. data/lib/active_support/core_ext/module.rb +13 -10
  94. data/lib/active_support/core_ext/name_error.rb +45 -4
  95. data/lib/active_support/core_ext/numeric/bytes.rb +22 -0
  96. data/lib/active_support/core_ext/numeric/conversions.rb +135 -127
  97. data/lib/active_support/core_ext/numeric/deprecated_conversions.rb +60 -0
  98. data/lib/active_support/core_ext/numeric/time.rb +37 -50
  99. data/lib/active_support/core_ext/numeric.rb +6 -3
  100. data/lib/active_support/core_ext/object/acts_like.rb +41 -6
  101. data/lib/active_support/core_ext/object/blank.rb +70 -20
  102. data/lib/active_support/core_ext/object/conversions.rb +6 -4
  103. data/lib/active_support/core_ext/object/deep_dup.rb +19 -10
  104. data/lib/active_support/core_ext/object/duplicable.rb +17 -47
  105. data/lib/active_support/core_ext/object/inclusion.rb +18 -15
  106. data/lib/active_support/core_ext/object/instance_variables.rb +3 -1
  107. data/lib/active_support/core_ext/object/json.rb +244 -0
  108. data/lib/active_support/core_ext/object/to_param.rb +3 -1
  109. data/lib/active_support/core_ext/object/to_query.rb +21 -8
  110. data/lib/active_support/core_ext/object/try.rb +106 -26
  111. data/lib/active_support/core_ext/object/with_options.rb +64 -5
  112. data/lib/active_support/core_ext/object.rb +14 -12
  113. data/lib/active_support/core_ext/pathname/existence.rb +21 -0
  114. data/lib/active_support/core_ext/pathname.rb +3 -0
  115. data/lib/active_support/core_ext/range/compare_range.rb +57 -0
  116. data/lib/active_support/core_ext/range/conversions.rb +37 -15
  117. data/lib/active_support/core_ext/range/deprecated_conversions.rb +26 -0
  118. data/lib/active_support/core_ext/range/each.rb +18 -17
  119. data/lib/active_support/core_ext/range/include_time_with_zone.rb +7 -0
  120. data/lib/active_support/core_ext/range/overlaps.rb +2 -0
  121. data/lib/active_support/core_ext/range.rb +7 -4
  122. data/lib/active_support/core_ext/regexp.rb +10 -1
  123. data/lib/active_support/core_ext/securerandom.rb +45 -0
  124. data/lib/active_support/core_ext/string/access.rb +42 -51
  125. data/lib/active_support/core_ext/string/behavior.rb +3 -1
  126. data/lib/active_support/core_ext/string/conversions.rb +18 -13
  127. data/lib/active_support/core_ext/string/exclude.rb +5 -3
  128. data/lib/active_support/core_ext/string/filters.rb +97 -7
  129. data/lib/active_support/core_ext/string/indent.rb +6 -4
  130. data/lib/active_support/core_ext/string/inflections.rb +106 -25
  131. data/lib/active_support/core_ext/string/inquiry.rb +4 -1
  132. data/lib/active_support/core_ext/string/multibyte.rb +18 -9
  133. data/lib/active_support/core_ext/string/output_safety.rb +227 -54
  134. data/lib/active_support/core_ext/string/starts_ends_with.rb +4 -2
  135. data/lib/active_support/core_ext/string/strip.rb +6 -5
  136. data/lib/active_support/core_ext/string/zones.rb +4 -1
  137. data/lib/active_support/core_ext/string.rb +15 -13
  138. data/lib/active_support/core_ext/symbol/starts_ends_with.rb +6 -0
  139. data/lib/active_support/core_ext/symbol.rb +3 -0
  140. data/lib/active_support/core_ext/time/acts_like.rb +3 -1
  141. data/lib/active_support/core_ext/time/calculations.rb +178 -116
  142. data/lib/active_support/core_ext/time/compatibility.rb +16 -0
  143. data/lib/active_support/core_ext/time/conversions.rb +37 -25
  144. data/lib/active_support/core_ext/time/deprecated_conversions.rb +22 -0
  145. data/lib/active_support/core_ext/time/zones.rb +44 -42
  146. data/lib/active_support/core_ext/time.rb +8 -5
  147. data/lib/active_support/core_ext/uri.rb +4 -25
  148. data/lib/active_support/core_ext.rb +4 -2
  149. data/lib/active_support/current_attributes/test_helper.rb +13 -0
  150. data/lib/active_support/current_attributes.rb +226 -0
  151. data/lib/active_support/dependencies/autoload.rb +3 -1
  152. data/lib/active_support/dependencies/interlock.rb +49 -0
  153. data/lib/active_support/dependencies/require_dependency.rb +28 -0
  154. data/lib/active_support/dependencies.rb +71 -696
  155. data/lib/active_support/deprecation/behaviors.rb +65 -16
  156. data/lib/active_support/deprecation/constant_accessor.rb +52 -0
  157. data/lib/active_support/deprecation/disallowed.rb +56 -0
  158. data/lib/active_support/deprecation/instance_delegator.rb +16 -2
  159. data/lib/active_support/deprecation/method_wrappers.rb +62 -21
  160. data/lib/active_support/deprecation/proxy_wrappers.rb +82 -31
  161. data/lib/active_support/deprecation/reporting.rb +81 -18
  162. data/lib/active_support/deprecation.rb +19 -11
  163. data/lib/active_support/descendants_tracker.rb +192 -34
  164. data/lib/active_support/digest.rb +22 -0
  165. data/lib/active_support/duration/iso8601_parser.rb +123 -0
  166. data/lib/active_support/duration/iso8601_serializer.rb +67 -0
  167. data/lib/active_support/duration.rb +437 -39
  168. data/lib/active_support/encrypted_configuration.rb +56 -0
  169. data/lib/active_support/encrypted_file.rb +117 -0
  170. data/lib/active_support/environment_inquirer.rb +20 -0
  171. data/lib/active_support/error_reporter.rb +117 -0
  172. data/lib/active_support/evented_file_update_checker.rb +170 -0
  173. data/lib/active_support/execution_context/test_helper.rb +13 -0
  174. data/lib/active_support/execution_context.rb +53 -0
  175. data/lib/active_support/execution_wrapper.rb +151 -0
  176. data/lib/active_support/executor/test_helper.rb +7 -0
  177. data/lib/active_support/executor.rb +8 -0
  178. data/lib/active_support/file_update_checker.rb +62 -37
  179. data/lib/active_support/fork_tracker.rb +71 -0
  180. data/lib/active_support/gem_version.rb +17 -0
  181. data/lib/active_support/gzip.rb +7 -5
  182. data/lib/active_support/hash_with_indifferent_access.rb +207 -54
  183. data/lib/active_support/html_safe_translation.rb +43 -0
  184. data/lib/active_support/i18n.rb +10 -6
  185. data/lib/active_support/i18n_railtie.rb +48 -19
  186. data/lib/active_support/inflections.rb +19 -12
  187. data/lib/active_support/inflector/inflections.rb +97 -37
  188. data/lib/active_support/inflector/methods.rb +192 -157
  189. data/lib/active_support/inflector/transliterate.rb +83 -33
  190. data/lib/active_support/inflector.rb +7 -5
  191. data/lib/active_support/isolated_execution_state.rb +64 -0
  192. data/lib/active_support/json/decoding.rb +37 -42
  193. data/lib/active_support/json/encoding.rb +93 -293
  194. data/lib/active_support/json.rb +4 -2
  195. data/lib/active_support/key_generator.rb +30 -47
  196. data/lib/active_support/lazy_load_hooks.rb +54 -21
  197. data/lib/active_support/locale/en.rb +33 -0
  198. data/lib/active_support/locale/en.yml +10 -4
  199. data/lib/active_support/log_subscriber/test_helper.rb +14 -12
  200. data/lib/active_support/log_subscriber.rb +61 -18
  201. data/lib/active_support/logger.rb +40 -4
  202. data/lib/active_support/logger_silence.rb +17 -20
  203. data/lib/active_support/logger_thread_safe_level.rb +69 -0
  204. data/lib/active_support/message_encryptor.rb +178 -55
  205. data/lib/active_support/message_verifier.rb +195 -26
  206. data/lib/active_support/messages/metadata.rb +80 -0
  207. data/lib/active_support/messages/rotation_configuration.rb +23 -0
  208. data/lib/active_support/messages/rotator.rb +57 -0
  209. data/lib/active_support/multibyte/chars.rb +45 -92
  210. data/lib/active_support/multibyte/unicode.rb +44 -377
  211. data/lib/active_support/multibyte.rb +5 -3
  212. data/lib/active_support/notifications/fanout.rb +177 -44
  213. data/lib/active_support/notifications/instrumenter.rb +117 -17
  214. data/lib/active_support/notifications.rb +106 -39
  215. data/lib/active_support/number_helper/number_converter.rb +181 -0
  216. data/lib/active_support/number_helper/number_to_currency_converter.rb +46 -0
  217. data/lib/active_support/number_helper/number_to_delimited_converter.rb +30 -0
  218. data/lib/active_support/number_helper/number_to_human_converter.rb +69 -0
  219. data/lib/active_support/number_helper/number_to_human_size_converter.rb +60 -0
  220. data/lib/active_support/number_helper/number_to_percentage_converter.rb +16 -0
  221. data/lib/active_support/number_helper/number_to_phone_converter.rb +59 -0
  222. data/lib/active_support/number_helper/number_to_rounded_converter.rb +59 -0
  223. data/lib/active_support/number_helper/rounding_helper.rb +46 -0
  224. data/lib/active_support/number_helper.rb +152 -394
  225. data/lib/active_support/option_merger.rb +18 -5
  226. data/lib/active_support/ordered_hash.rb +8 -6
  227. data/lib/active_support/ordered_options.rb +43 -7
  228. data/lib/active_support/parameter_filter.rb +138 -0
  229. data/lib/active_support/per_thread_registry.rb +24 -11
  230. data/lib/active_support/proxy_object.rb +2 -0
  231. data/lib/active_support/rails.rb +10 -11
  232. data/lib/active_support/railtie.rb +118 -12
  233. data/lib/active_support/reloader.rb +130 -0
  234. data/lib/active_support/rescuable.rb +112 -57
  235. data/lib/active_support/ruby_features.rb +7 -0
  236. data/lib/active_support/secure_compare_rotator.rb +51 -0
  237. data/lib/active_support/security_utils.rb +38 -0
  238. data/lib/active_support/string_inquirer.rb +11 -4
  239. data/lib/active_support/subscriber.rb +109 -39
  240. data/lib/active_support/tagged_logging.rb +54 -17
  241. data/lib/active_support/test_case.rb +121 -37
  242. data/lib/active_support/testing/assertions.rb +177 -39
  243. data/lib/active_support/testing/autorun.rb +5 -3
  244. data/lib/active_support/testing/constant_lookup.rb +3 -6
  245. data/lib/active_support/testing/declarative.rb +10 -22
  246. data/lib/active_support/testing/deprecation.rb +65 -11
  247. data/lib/active_support/testing/file_fixtures.rb +38 -0
  248. data/lib/active_support/testing/isolation.rb +56 -87
  249. data/lib/active_support/testing/method_call_assertions.rb +70 -0
  250. data/lib/active_support/testing/parallelization/server.rb +82 -0
  251. data/lib/active_support/testing/parallelization/worker.rb +103 -0
  252. data/lib/active_support/testing/parallelization.rb +55 -0
  253. data/lib/active_support/testing/parallelize_executor.rb +76 -0
  254. data/lib/active_support/testing/setup_and_teardown.rb +30 -10
  255. data/lib/active_support/testing/stream.rb +41 -0
  256. data/lib/active_support/testing/tagged_logging.rb +6 -4
  257. data/lib/active_support/testing/time_helpers.rb +246 -0
  258. data/lib/active_support/time.rb +13 -13
  259. data/lib/active_support/time_with_zone.rb +315 -90
  260. data/lib/active_support/values/time_zone.rb +306 -135
  261. data/lib/active_support/version.rb +6 -7
  262. data/lib/active_support/xml_mini/jdom.rb +117 -115
  263. data/lib/active_support/xml_mini/libxml.rb +22 -21
  264. data/lib/active_support/xml_mini/libxmlsax.rb +17 -19
  265. data/lib/active_support/xml_mini/nokogiri.rb +19 -19
  266. data/lib/active_support/xml_mini/nokogirisax.rb +16 -17
  267. data/lib/active_support/xml_mini/rexml.rb +25 -17
  268. data/lib/active_support/xml_mini.rb +67 -56
  269. data/lib/active_support.rb +58 -3
  270. metadata +125 -66
  271. data/lib/active_support/basic_object.rb +0 -11
  272. data/lib/active_support/buffered_logger.rb +0 -21
  273. data/lib/active_support/concurrency/latch.rb +0 -27
  274. data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -7
  275. data/lib/active_support/core_ext/array/uniq_by.rb +0 -19
  276. data/lib/active_support/core_ext/class/delegating_attributes.rb +0 -40
  277. data/lib/active_support/core_ext/date_time/zones.rb +0 -24
  278. data/lib/active_support/core_ext/hash/diff.rb +0 -14
  279. data/lib/active_support/core_ext/kernel/agnostics.rb +0 -11
  280. data/lib/active_support/core_ext/kernel/debugger.rb +0 -10
  281. data/lib/active_support/core_ext/logger.rb +0 -67
  282. data/lib/active_support/core_ext/marshal.rb +0 -21
  283. data/lib/active_support/core_ext/module/qualified_const.rb +0 -52
  284. data/lib/active_support/core_ext/module/reachable.rb +0 -8
  285. data/lib/active_support/core_ext/object/to_json.rb +0 -27
  286. data/lib/active_support/core_ext/proc.rb +0 -17
  287. data/lib/active_support/core_ext/range/include_range.rb +0 -23
  288. data/lib/active_support/core_ext/string/encoding.rb +0 -8
  289. data/lib/active_support/core_ext/struct.rb +0 -6
  290. data/lib/active_support/core_ext/thread.rb +0 -79
  291. data/lib/active_support/core_ext/time/marshal.rb +0 -30
  292. data/lib/active_support/file_watcher.rb +0 -36
  293. data/lib/active_support/json/variable.rb +0 -18
  294. data/lib/active_support/testing/pending.rb +0 -14
  295. data/lib/active_support/values/unicode_tables.dat +0 -0
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # in case active_support/inflector is required without the rest of active_support
2
- require 'active_support/inflector/inflections'
3
- require 'active_support/inflector/transliterate'
4
- require 'active_support/inflector/methods'
4
+ require "active_support/inflector/inflections"
5
+ require "active_support/inflector/transliterate"
6
+ require "active_support/inflector/methods"
5
7
 
6
- require 'active_support/inflections'
7
- require 'active_support/core_ext/string/inflections'
8
+ require "active_support/inflections"
9
+ require "active_support/core_ext/string/inflections"
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "fiber"
4
+
5
+ module ActiveSupport
6
+ module IsolatedExecutionState # :nodoc:
7
+ @isolation_level = :thread
8
+
9
+ Thread.attr_accessor :active_support_execution_state
10
+ Fiber.attr_accessor :active_support_execution_state
11
+
12
+ class << self
13
+ attr_reader :isolation_level
14
+
15
+ def isolation_level=(level)
16
+ unless %i(thread fiber).include?(level)
17
+ raise ArgumentError, "isolation_level must be `:thread` or `:fiber`, got: `#{level.inspect}`"
18
+ end
19
+
20
+ if level != isolation_level
21
+ clear
22
+ singleton_class.alias_method(:current, "current_#{level}")
23
+ singleton_class.send(:private, :current)
24
+ @isolation_level = level
25
+ end
26
+ end
27
+
28
+ def unique_id
29
+ self[:__id__] ||= Object.new
30
+ end
31
+
32
+ def [](key)
33
+ current[key]
34
+ end
35
+
36
+ def []=(key, value)
37
+ current[key] = value
38
+ end
39
+
40
+ def key?(key)
41
+ current.key?(key)
42
+ end
43
+
44
+ def delete(key)
45
+ current.delete(key)
46
+ end
47
+
48
+ def clear
49
+ current.clear
50
+ end
51
+
52
+ private
53
+ def current_thread
54
+ Thread.current.active_support_execution_state ||= {}
55
+ end
56
+
57
+ def current_fiber
58
+ Fiber.current.active_support_execution_state ||= {}
59
+ end
60
+
61
+ alias_method :current, :current_thread
62
+ end
63
+ end
64
+ end
@@ -1,20 +1,27 @@
1
- require 'active_support/core_ext/module/attribute_accessors'
2
- require 'active_support/core_ext/module/delegation'
3
- require 'multi_json'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/module/attribute_accessors"
4
+ require "active_support/core_ext/module/delegation"
5
+ require "json"
4
6
 
5
7
  module ActiveSupport
6
8
  # Look for and parse json strings that look like ISO 8601 times.
7
9
  mattr_accessor :parse_json_times
8
10
 
9
11
  module JSON
12
+ # matches YAML-formatted dates
13
+ DATE_REGEX = /\A\d{4}-\d{2}-\d{2}\z/
14
+ DATETIME_REGEX = /\A(?:\d{4}-\d{2}-\d{2}|\d{4}-\d{1,2}-\d{1,2}[T \t]+\d{1,2}:\d{2}:\d{2}(\.[0-9]*)?(([ \t]*)Z|[-+]\d{2}?(:\d{2})?)?)\z/
15
+
10
16
  class << self
11
17
  # Parses a JSON string (JavaScript Object Notation) into a hash.
12
- # See www.json.org for more info.
18
+ # See http://www.json.org for more info.
13
19
  #
14
20
  # ActiveSupport::JSON.decode("{\"team\":\"rails\",\"players\":\"36\"}")
15
21
  # => {"team" => "rails", "players" => "36"}
16
- def decode(json, options ={})
17
- data = MultiJson.load(json, options)
22
+ def decode(json)
23
+ data = ::JSON.parse(json, quirks_mode: true)
24
+
18
25
  if ActiveSupport.parse_json_times
19
26
  convert_dates_from(data)
20
27
  else
@@ -22,23 +29,6 @@ module ActiveSupport
22
29
  end
23
30
  end
24
31
 
25
- def engine
26
- MultiJson.adapter
27
- end
28
- alias :backend :engine
29
-
30
- def engine=(name)
31
- MultiJson.use(name)
32
- end
33
- alias :backend= :engine=
34
-
35
- def with_backend(name)
36
- old_backend, self.backend = backend, name
37
- yield
38
- ensure
39
- self.backend = old_backend
40
- end
41
-
42
32
  # Returns the class of the error that will be raised when there is an
43
33
  # error in decoding JSON. Using this method means you won't directly
44
34
  # depend on the ActiveSupport's JSON implementation, in case it changes
@@ -50,31 +40,36 @@ module ActiveSupport
50
40
  # Rails.logger.warn("Attempted to decode invalid JSON: #{some_string}")
51
41
  # end
52
42
  def parse_error
53
- MultiJson::DecodeError
43
+ ::JSON::ParserError
54
44
  end
55
45
 
56
46
  private
57
-
58
- def convert_dates_from(data)
59
- case data
60
- when nil
61
- nil
62
- when DATE_REGEX
63
- begin
64
- DateTime.parse(data)
65
- rescue ArgumentError
47
+ def convert_dates_from(data)
48
+ case data
49
+ when nil
50
+ nil
51
+ when DATE_REGEX
52
+ begin
53
+ Date.parse(data)
54
+ rescue ArgumentError
55
+ data
56
+ end
57
+ when DATETIME_REGEX
58
+ begin
59
+ Time.zone.parse(data)
60
+ rescue ArgumentError
61
+ data
62
+ end
63
+ when Array
64
+ data.map! { |d| convert_dates_from(d) }
65
+ when Hash
66
+ data.transform_values! do |value|
67
+ convert_dates_from(value)
68
+ end
69
+ else
66
70
  data
67
71
  end
68
- when Array
69
- data.map! { |d| convert_dates_from(d) }
70
- when Hash
71
- data.each do |key, value|
72
- data[key] = convert_dates_from(value)
73
- end
74
- else
75
- data
76
72
  end
77
- end
78
73
  end
79
74
  end
80
75
  end
@@ -1,338 +1,138 @@
1
- require 'active_support/core_ext/object/to_json'
2
- require 'active_support/core_ext/module/delegation'
3
- require 'active_support/json/variable'
1
+ # frozen_string_literal: true
4
2
 
5
- require 'bigdecimal'
6
- require 'active_support/core_ext/big_decimal/conversions' # for #to_s
7
- require 'active_support/core_ext/hash/except'
8
- require 'active_support/core_ext/hash/slice'
9
- require 'active_support/core_ext/object/instance_variables'
10
- require 'time'
11
- require 'active_support/core_ext/time/conversions'
12
- require 'active_support/core_ext/date_time/conversions'
13
- require 'active_support/core_ext/date/conversions'
14
- require 'set'
3
+ require "active_support/core_ext/object/json"
4
+ require "active_support/core_ext/module/delegation"
15
5
 
16
6
  module ActiveSupport
17
7
  class << self
18
8
  delegate :use_standard_json_time_format, :use_standard_json_time_format=,
9
+ :time_precision, :time_precision=,
19
10
  :escape_html_entities_in_json, :escape_html_entities_in_json=,
20
- :encode_big_decimal_as_string, :encode_big_decimal_as_string=,
21
- :to => :'ActiveSupport::JSON::Encoding'
11
+ :json_encoder, :json_encoder=,
12
+ to: :'ActiveSupport::JSON::Encoding'
22
13
  end
23
14
 
24
15
  module JSON
25
- # matches YAML-formatted dates
26
- DATE_REGEX = /^(?:\d{4}-\d{2}-\d{2}|\d{4}-\d{1,2}-\d{1,2}[T \t]+\d{1,2}:\d{2}:\d{2}(\.[0-9]*)?(([ \t]*)Z|[-+]\d{2}?(:\d{2})?))$/
27
-
28
16
  # Dumps objects in JSON (JavaScript Object Notation).
29
- # See www.json.org for more info.
17
+ # See http://www.json.org for more info.
30
18
  #
31
19
  # ActiveSupport::JSON.encode({ team: 'rails', players: '36' })
32
20
  # # => "{\"team\":\"rails\",\"players\":\"36\"}"
33
21
  def self.encode(value, options = nil)
34
- Encoding::Encoder.new(options).encode(value)
22
+ Encoding.json_encoder.new(options).encode(value)
35
23
  end
36
24
 
37
- module Encoding #:nodoc:
38
- class CircularReferenceError < StandardError; end
39
-
40
- class Encoder
25
+ module Encoding # :nodoc:
26
+ class JSONGemEncoder # :nodoc:
41
27
  attr_reader :options
42
28
 
43
29
  def initialize(options = nil)
44
30
  @options = options || {}
45
- @seen = Set.new
46
31
  end
47
32
 
48
- def encode(value, use_options = true)
49
- check_for_circular_references(value) do
50
- jsonified = use_options ? value.as_json(options_for(value)) : value.as_json
51
- jsonified.encode_json(self)
52
- end
33
+ # Encode the given object into a JSON string
34
+ def encode(value)
35
+ stringify jsonify value.as_json(options.dup)
53
36
  end
54
37
 
55
- # like encode, but only calls as_json, without encoding to string.
56
- def as_json(value, use_options = true)
57
- check_for_circular_references(value) do
58
- use_options ? value.as_json(options_for(value)) : value.as_json
59
- end
60
- end
38
+ private
39
+ # Rails does more escaping than the JSON gem natively does (we
40
+ # escape \u2028 and \u2029 and optionally >, <, & to work around
41
+ # certain browser problems).
42
+ ESCAPED_CHARS = {
43
+ "\u2028" => '\u2028',
44
+ "\u2029" => '\u2029',
45
+ ">" => '\u003e',
46
+ "<" => '\u003c',
47
+ "&" => '\u0026',
48
+ }
49
+
50
+ ESCAPE_REGEX_WITH_HTML_ENTITIES = /[\u2028\u2029><&]/u
51
+ ESCAPE_REGEX_WITHOUT_HTML_ENTITIES = /[\u2028\u2029]/u
52
+
53
+ # This class wraps all the strings we see and does the extra escaping
54
+ class EscapedString < String # :nodoc:
55
+ def to_json(*)
56
+ if Encoding.escape_html_entities_in_json
57
+ s = super
58
+ s.gsub! ESCAPE_REGEX_WITH_HTML_ENTITIES, ESCAPED_CHARS
59
+ s
60
+ else
61
+ s = super
62
+ s.gsub! ESCAPE_REGEX_WITHOUT_HTML_ENTITIES, ESCAPED_CHARS
63
+ s
64
+ end
65
+ end
61
66
 
62
- def options_for(value)
63
- if value.is_a?(Array) || value.is_a?(Hash)
64
- # hashes and arrays need to get encoder in the options, so that
65
- # they can detect circular references.
66
- options.merge(:encoder => self)
67
- else
68
- options.dup
67
+ def to_s
68
+ self
69
+ end
69
70
  end
70
- end
71
-
72
- def escape(string)
73
- Encoding.escape(string)
74
- end
75
71
 
76
- private
77
- def check_for_circular_references(value)
78
- unless @seen.add?(value.__id__)
79
- raise CircularReferenceError, 'object references itself'
72
+ # Mark these as private so we don't leak encoding-specific constructs
73
+ private_constant :ESCAPED_CHARS, :ESCAPE_REGEX_WITH_HTML_ENTITIES,
74
+ :ESCAPE_REGEX_WITHOUT_HTML_ENTITIES, :EscapedString
75
+
76
+ # Convert an object into a "JSON-ready" representation composed of
77
+ # primitives like Hash, Array, String, Numeric,
78
+ # and +true+/+false+/+nil+.
79
+ # Recursively calls #as_json to the object to recursively build a
80
+ # fully JSON-ready object.
81
+ #
82
+ # This allows developers to implement #as_json without having to
83
+ # worry about what base types of objects they are allowed to return
84
+ # or having to remember to call #as_json recursively.
85
+ #
86
+ # Note: the +options+ hash passed to +object.to_json+ is only passed
87
+ # to +object.as_json+, not any of this method's recursive +#as_json+
88
+ # calls.
89
+ def jsonify(value)
90
+ case value
91
+ when String
92
+ EscapedString.new(value)
93
+ when Numeric, NilClass, TrueClass, FalseClass
94
+ value.as_json
95
+ when Hash
96
+ result = {}
97
+ value.each do |k, v|
98
+ result[jsonify(k)] = jsonify(v)
99
+ end
100
+ result
101
+ when Array
102
+ value.map { |v| jsonify(v) }
103
+ else
104
+ jsonify value.as_json
80
105
  end
81
- yield
82
- ensure
83
- @seen.delete(value.__id__)
84
106
  end
85
- end
86
-
87
107
 
88
- ESCAPED_CHARS = {
89
- "\x00" => '\u0000', "\x01" => '\u0001', "\x02" => '\u0002',
90
- "\x03" => '\u0003', "\x04" => '\u0004', "\x05" => '\u0005',
91
- "\x06" => '\u0006', "\x07" => '\u0007', "\x0B" => '\u000B',
92
- "\x0E" => '\u000E', "\x0F" => '\u000F', "\x10" => '\u0010',
93
- "\x11" => '\u0011', "\x12" => '\u0012', "\x13" => '\u0013',
94
- "\x14" => '\u0014', "\x15" => '\u0015', "\x16" => '\u0016',
95
- "\x17" => '\u0017', "\x18" => '\u0018', "\x19" => '\u0019',
96
- "\x1A" => '\u001A', "\x1B" => '\u001B', "\x1C" => '\u001C',
97
- "\x1D" => '\u001D', "\x1E" => '\u001E', "\x1F" => '\u001F',
98
- "\010" => '\b',
99
- "\f" => '\f',
100
- "\n" => '\n',
101
- "\r" => '\r',
102
- "\t" => '\t',
103
- '"' => '\"',
104
- '\\' => '\\\\',
105
- '>' => '\u003E',
106
- '<' => '\u003C',
107
- '&' => '\u0026' }
108
+ # Encode a "jsonified" Ruby data structure using the JSON gem
109
+ def stringify(jsonified)
110
+ ::JSON.generate(jsonified, quirks_mode: true, max_nesting: false)
111
+ end
112
+ end
108
113
 
109
114
  class << self
110
115
  # If true, use ISO 8601 format for dates and times. Otherwise, fall back
111
116
  # to the Active Support legacy format.
112
117
  attr_accessor :use_standard_json_time_format
113
118
 
114
- # If false, serializes BigDecimal objects as numeric instead of wrapping
115
- # them in a string.
116
- attr_accessor :encode_big_decimal_as_string
117
-
118
- attr_accessor :escape_regex
119
- attr_reader :escape_html_entities_in_json
119
+ # If true, encode >, <, & as escaped unicode sequences (e.g. > as \u003e)
120
+ # as a safety measure.
121
+ attr_accessor :escape_html_entities_in_json
120
122
 
121
- def escape_html_entities_in_json=(value)
122
- self.escape_regex = \
123
- if @escape_html_entities_in_json = value
124
- /[\x00-\x1F"\\><&]/
125
- else
126
- /[\x00-\x1F"\\]/
127
- end
128
- end
123
+ # Sets the precision of encoded time values.
124
+ # Defaults to 3 (equivalent to millisecond precision)
125
+ attr_accessor :time_precision
129
126
 
130
- def escape(string)
131
- string = string.encode(::Encoding::UTF_8, :undef => :replace).force_encoding(::Encoding::BINARY)
132
- json = string.gsub(escape_regex) { |s| ESCAPED_CHARS[s] }
133
- json = %("#{json}")
134
- json.force_encoding(::Encoding::UTF_8)
135
- json
136
- end
127
+ # Sets the encoder used by Rails to encode Ruby objects into JSON strings
128
+ # in +Object#to_json+ and +ActiveSupport::JSON.encode+.
129
+ attr_accessor :json_encoder
137
130
  end
138
131
 
139
132
  self.use_standard_json_time_format = true
140
133
  self.escape_html_entities_in_json = true
141
- self.encode_big_decimal_as_string = true
142
- end
143
- end
144
- end
145
-
146
- class Object
147
- def as_json(options = nil) #:nodoc:
148
- if respond_to?(:to_hash)
149
- to_hash
150
- else
151
- instance_values
152
- end
153
- end
154
- end
155
-
156
- class Struct #:nodoc:
157
- def as_json(options = nil)
158
- Hash[members.zip(values)]
159
- end
160
- end
161
-
162
- class TrueClass
163
- def as_json(options = nil) #:nodoc:
164
- self
165
- end
166
-
167
- def encode_json(encoder) #:nodoc:
168
- to_s
169
- end
170
- end
171
-
172
- class FalseClass
173
- def as_json(options = nil) #:nodoc:
174
- self
175
- end
176
-
177
- def encode_json(encoder) #:nodoc:
178
- to_s
179
- end
180
- end
181
-
182
- class NilClass
183
- def as_json(options = nil) #:nodoc:
184
- self
185
- end
186
-
187
- def encode_json(encoder) #:nodoc:
188
- 'null'
189
- end
190
- end
191
-
192
- class String
193
- def as_json(options = nil) #:nodoc:
194
- self
195
- end
196
-
197
- def encode_json(encoder) #:nodoc:
198
- encoder.escape(self)
199
- end
200
- end
201
-
202
- class Symbol
203
- def as_json(options = nil) #:nodoc:
204
- to_s
205
- end
206
- end
207
-
208
- class Numeric
209
- def as_json(options = nil) #:nodoc:
210
- self
211
- end
212
-
213
- def encode_json(encoder) #:nodoc:
214
- to_s
215
- end
216
- end
217
-
218
- class Float
219
- # Encoding Infinity or NaN to JSON should return "null". The default returns
220
- # "Infinity" or "NaN" which breaks parsing the JSON. E.g. JSON.parse('[NaN]').
221
- def as_json(options = nil) #:nodoc:
222
- finite? ? self : nil
223
- end
224
- end
225
-
226
- class BigDecimal
227
- # A BigDecimal would be naturally represented as a JSON number. Most libraries,
228
- # however, parse non-integer JSON numbers directly as floats. Clients using
229
- # those libraries would get in general a wrong number and no way to recover
230
- # other than manually inspecting the string with the JSON code itself.
231
- #
232
- # That's why a JSON string is returned. The JSON literal is not numeric, but
233
- # if the other end knows by contract that the data is supposed to be a
234
- # BigDecimal, it still has the chance to post-process the string and get the
235
- # real value.
236
- #
237
- # Use <tt>ActiveSupport.encode_big_decimal_as_string = true</tt> to
238
- # override this behavior.
239
- def as_json(options = nil) #:nodoc:
240
- if finite?
241
- ActiveSupport.encode_big_decimal_as_string ? to_s : self
242
- else
243
- nil
244
- end
245
- end
246
- end
247
-
248
- class Regexp
249
- def as_json(options = nil) #:nodoc:
250
- to_s
251
- end
252
- end
253
-
254
- module Enumerable
255
- def as_json(options = nil) #:nodoc:
256
- to_a.as_json(options)
257
- end
258
- end
259
-
260
- class Range
261
- def as_json(options = nil) #:nodoc:
262
- to_s
263
- end
264
- end
265
-
266
- class Array
267
- def as_json(options = nil) #:nodoc:
268
- # use encoder as a proxy to call as_json on all elements, to protect from circular references
269
- encoder = options && options[:encoder] || ActiveSupport::JSON::Encoding::Encoder.new(options)
270
- map { |v| encoder.as_json(v, options) }
271
- end
272
-
273
- def encode_json(encoder) #:nodoc:
274
- # we assume here that the encoder has already run as_json on self and the elements, so we run encode_json directly
275
- "[#{map { |v| v.encode_json(encoder) } * ','}]"
276
- end
277
- end
278
-
279
- class Hash
280
- def as_json(options = nil) #:nodoc:
281
- # create a subset of the hash by applying :only or :except
282
- subset = if options
283
- if attrs = options[:only]
284
- slice(*Array(attrs))
285
- elsif attrs = options[:except]
286
- except(*Array(attrs))
287
- else
288
- self
289
- end
290
- else
291
- self
292
- end
293
-
294
- # use encoder as a proxy to call as_json on all values in the subset, to protect from circular references
295
- encoder = options && options[:encoder] || ActiveSupport::JSON::Encoding::Encoder.new(options)
296
- Hash[subset.map { |k, v| [k.to_s, encoder.as_json(v, options)] }]
297
- end
298
-
299
- def encode_json(encoder) #:nodoc:
300
- # values are encoded with use_options = false, because we don't want hash representations from ActiveModel to be
301
- # processed once again with as_json with options, as this could cause unexpected results (i.e. missing fields);
302
-
303
- # on the other hand, we need to run as_json on the elements, because the model representation may contain fields
304
- # like Time/Date in their original (not jsonified) form, etc.
305
-
306
- "{#{map { |k,v| "#{encoder.encode(k.to_s)}:#{encoder.encode(v, false)}" } * ','}}"
307
- end
308
- end
309
-
310
- class Time
311
- def as_json(options = nil) #:nodoc:
312
- if ActiveSupport.use_standard_json_time_format
313
- xmlschema
314
- else
315
- %(#{strftime("%Y/%m/%d %H:%M:%S")} #{formatted_offset(false)})
316
- end
317
- end
318
- end
319
-
320
- class Date
321
- def as_json(options = nil) #:nodoc:
322
- if ActiveSupport.use_standard_json_time_format
323
- strftime("%Y-%m-%d")
324
- else
325
- strftime("%Y/%m/%d")
326
- end
327
- end
328
- end
329
-
330
- class DateTime
331
- def as_json(options = nil) #:nodoc:
332
- if ActiveSupport.use_standard_json_time_format
333
- xmlschema
334
- else
335
- strftime('%Y/%m/%d %H:%M:%S %z')
134
+ self.json_encoder = JSONGemEncoder
135
+ self.time_precision = 3
336
136
  end
337
137
  end
338
138
  end
@@ -1,2 +1,4 @@
1
- require 'active_support/json/decoding'
2
- require 'active_support/json/encoding'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/json/decoding"
4
+ require "active_support/json/encoding"