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
@@ -1,9 +1,10 @@
1
- module ActiveSupport
2
- module VERSION #:nodoc:
3
- MAJOR = 1
4
- MINOR = 2
5
- TINY = 4
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "gem_version"
6
4
 
7
- STRING = [MAJOR, MINOR, TINY].join('.')
5
+ module ActiveSupport
6
+ # Returns the currently loaded version of Active Support as a +Gem::Version+.
7
+ def self.version
8
+ gem_version
8
9
  end
9
10
  end
@@ -0,0 +1,175 @@
1
+ # frozen_string_literal: true
2
+
3
+ raise "JRuby is required to use the JDOM backend for XmlMini" unless RUBY_PLATFORM.include?("java")
4
+
5
+ require "jruby"
6
+ include Java
7
+
8
+ require "active_support/core_ext/object/blank"
9
+
10
+ java_import javax.xml.parsers.DocumentBuilder unless defined? DocumentBuilder
11
+ java_import javax.xml.parsers.DocumentBuilderFactory unless defined? DocumentBuilderFactory
12
+ java_import java.io.StringReader unless defined? StringReader
13
+ java_import org.xml.sax.InputSource unless defined? InputSource
14
+ java_import org.xml.sax.Attributes unless defined? Attributes
15
+ java_import org.w3c.dom.Node unless defined? Node
16
+
17
+ module ActiveSupport
18
+ module XmlMini_JDOM # :nodoc:
19
+ extend self
20
+
21
+ CONTENT_KEY = "__content__"
22
+
23
+ # Parse an XML Document string or IO into a simple hash using Java's jdom.
24
+ # data::
25
+ # XML Document string or IO to parse
26
+ def parse(data)
27
+ if data.respond_to?(:read)
28
+ data = data.read
29
+ end
30
+
31
+ if data.blank?
32
+ {}
33
+ else
34
+ @dbf = DocumentBuilderFactory.new_instance
35
+ # secure processing of java xml
36
+ # https://archive.is/9xcQQ
37
+ @dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false)
38
+ @dbf.setFeature("http://xml.org/sax/features/external-general-entities", false)
39
+ @dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false)
40
+ @dbf.setFeature(javax.xml.XMLConstants::FEATURE_SECURE_PROCESSING, true)
41
+ xml_string_reader = StringReader.new(data)
42
+ xml_input_source = InputSource.new(xml_string_reader)
43
+ doc = @dbf.new_document_builder.parse(xml_input_source)
44
+ merge_element!({ CONTENT_KEY => "" }, doc.document_element, XmlMini.depth)
45
+ end
46
+ end
47
+
48
+ private
49
+ # Convert an XML element and merge into the hash
50
+ #
51
+ # hash::
52
+ # Hash to merge the converted element into.
53
+ # element::
54
+ # XML element to merge into hash
55
+ def merge_element!(hash, element, depth)
56
+ raise "Document too deep!" if depth == 0
57
+ delete_empty(hash)
58
+ merge!(hash, element.tag_name, collapse(element, depth))
59
+ end
60
+
61
+ def delete_empty(hash)
62
+ hash.delete(CONTENT_KEY) if hash[CONTENT_KEY] == ""
63
+ end
64
+
65
+ # Actually converts an XML document element into a data structure.
66
+ #
67
+ # element::
68
+ # The document element to be collapsed.
69
+ def collapse(element, depth)
70
+ hash = get_attributes(element)
71
+
72
+ child_nodes = element.child_nodes
73
+ if child_nodes.length > 0
74
+ (0...child_nodes.length).each do |i|
75
+ child = child_nodes.item(i)
76
+ merge_element!(hash, child, depth - 1) unless child.node_type == Node::TEXT_NODE
77
+ end
78
+ merge_texts!(hash, element) unless empty_content?(element)
79
+ hash
80
+ else
81
+ merge_texts!(hash, element)
82
+ end
83
+ end
84
+
85
+ # Merge all the texts of an element into the hash
86
+ #
87
+ # hash::
88
+ # Hash to add the converted element to.
89
+ # element::
90
+ # XML element whose texts are to me merged into the hash
91
+ def merge_texts!(hash, element)
92
+ delete_empty(hash)
93
+ text_children = texts(element)
94
+ if text_children.join.empty?
95
+ hash
96
+ else
97
+ # must use value to prevent double-escaping
98
+ merge!(hash, CONTENT_KEY, text_children.join)
99
+ end
100
+ end
101
+
102
+ # Adds a new key/value pair to an existing Hash. If the key to be added
103
+ # already exists and the existing value associated with key is not
104
+ # an Array, it will be wrapped in an Array. Then the new value is
105
+ # appended to that Array.
106
+ #
107
+ # hash::
108
+ # Hash to add key/value pair to.
109
+ # key::
110
+ # Key to be added.
111
+ # value::
112
+ # Value to be associated with key.
113
+ def merge!(hash, key, value)
114
+ if hash.has_key?(key)
115
+ if hash[key].instance_of?(Array)
116
+ hash[key] << value
117
+ else
118
+ hash[key] = [hash[key], value]
119
+ end
120
+ elsif value.instance_of?(Array)
121
+ hash[key] = [value]
122
+ else
123
+ hash[key] = value
124
+ end
125
+ hash
126
+ end
127
+
128
+ # Converts the attributes array of an XML element into a hash.
129
+ # Returns an empty Hash if node has no attributes.
130
+ #
131
+ # element::
132
+ # XML element to extract attributes from.
133
+ def get_attributes(element)
134
+ attribute_hash = {}
135
+ attributes = element.attributes
136
+ (0...attributes.length).each do |i|
137
+ attribute_hash[CONTENT_KEY] ||= ""
138
+ attribute_hash[attributes.item(i).name] = attributes.item(i).value
139
+ end
140
+ attribute_hash
141
+ end
142
+
143
+ # Determines if a document element has text content
144
+ #
145
+ # element::
146
+ # XML element to be checked.
147
+ def texts(element)
148
+ texts = []
149
+ child_nodes = element.child_nodes
150
+ (0...child_nodes.length).each do |i|
151
+ item = child_nodes.item(i)
152
+ if item.node_type == Node::TEXT_NODE
153
+ texts << item.get_data
154
+ end
155
+ end
156
+ texts
157
+ end
158
+
159
+ # Determines if a document element has text content
160
+ #
161
+ # element::
162
+ # XML element to be checked.
163
+ def empty_content?(element)
164
+ text = +""
165
+ child_nodes = element.child_nodes
166
+ (0...child_nodes.length).each do |i|
167
+ item = child_nodes.item(i)
168
+ if item.node_type == Node::TEXT_NODE
169
+ text << item.get_data.strip
170
+ end
171
+ end
172
+ text.strip.length == 0
173
+ end
174
+ end
175
+ end
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "libxml"
4
+ require "active_support/core_ext/object/blank"
5
+ require "stringio"
6
+
7
+ module ActiveSupport
8
+ module XmlMini_LibXML # :nodoc:
9
+ extend self
10
+
11
+ # Parse an XML Document string or IO into a simple hash using libxml.
12
+ # data::
13
+ # XML Document string or IO to parse
14
+ def parse(data)
15
+ if !data.respond_to?(:read)
16
+ data = StringIO.new(data || "")
17
+ end
18
+
19
+ if data.eof?
20
+ {}
21
+ else
22
+ LibXML::XML::Parser.io(data).parse.to_hash
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ module LibXML # :nodoc:
29
+ module Conversions # :nodoc:
30
+ module Document # :nodoc:
31
+ def to_hash
32
+ root.to_hash
33
+ end
34
+ end
35
+
36
+ module Node # :nodoc:
37
+ CONTENT_ROOT = "__content__"
38
+
39
+ # Convert XML document to hash.
40
+ #
41
+ # hash::
42
+ # Hash to merge the converted element into.
43
+ def to_hash(hash = {})
44
+ node_hash = {}
45
+
46
+ # Insert node hash into parent hash correctly.
47
+ case hash[name]
48
+ when Array then hash[name] << node_hash
49
+ when Hash then hash[name] = [hash[name], node_hash]
50
+ when nil then hash[name] = node_hash
51
+ end
52
+
53
+ # Handle child elements
54
+ each_child do |c|
55
+ if c.element?
56
+ c.to_hash(node_hash)
57
+ elsif c.text? || c.cdata?
58
+ node_hash[CONTENT_ROOT] ||= +""
59
+ node_hash[CONTENT_ROOT] << c.content
60
+ end
61
+ end
62
+
63
+ # Remove content node if it is blank
64
+ if node_hash.length > 1 && node_hash[CONTENT_ROOT].blank?
65
+ node_hash.delete(CONTENT_ROOT)
66
+ end
67
+
68
+ # Handle attributes
69
+ each_attr { |a| node_hash[a.name] = a.value }
70
+
71
+ hash
72
+ end
73
+ end
74
+ end
75
+ end
76
+
77
+ # :enddoc:
78
+
79
+ LibXML::XML::Document.include(LibXML::Conversions::Document)
80
+ LibXML::XML::Node.include(LibXML::Conversions::Node)
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "libxml"
4
+ require "active_support/core_ext/object/blank"
5
+ require "stringio"
6
+
7
+ module ActiveSupport
8
+ module XmlMini_LibXMLSAX # :nodoc:
9
+ extend self
10
+
11
+ # Class that will build the hash while the XML document
12
+ # is being parsed using SAX events.
13
+ class HashBuilder
14
+ include LibXML::XML::SaxParser::Callbacks
15
+
16
+ CONTENT_KEY = "__content__"
17
+ HASH_SIZE_KEY = "__hash_size__"
18
+
19
+ attr_reader :hash
20
+
21
+ def current_hash
22
+ @hash_stack.last
23
+ end
24
+
25
+ def on_start_document
26
+ @hash = { CONTENT_KEY => +"" }
27
+ @hash_stack = [@hash]
28
+ end
29
+
30
+ def on_end_document
31
+ @hash = @hash_stack.pop
32
+ @hash.delete(CONTENT_KEY)
33
+ end
34
+
35
+ def on_start_element(name, attrs = {})
36
+ new_hash = { CONTENT_KEY => +"" }.merge!(attrs)
37
+ new_hash[HASH_SIZE_KEY] = new_hash.size + 1
38
+
39
+ case current_hash[name]
40
+ when Array then current_hash[name] << new_hash
41
+ when Hash then current_hash[name] = [current_hash[name], new_hash]
42
+ when nil then current_hash[name] = new_hash
43
+ end
44
+
45
+ @hash_stack.push(new_hash)
46
+ end
47
+
48
+ def on_end_element(name)
49
+ if current_hash.length > current_hash.delete(HASH_SIZE_KEY) && current_hash[CONTENT_KEY].blank? || current_hash[CONTENT_KEY] == ""
50
+ current_hash.delete(CONTENT_KEY)
51
+ end
52
+ @hash_stack.pop
53
+ end
54
+
55
+ def on_characters(string)
56
+ current_hash[CONTENT_KEY] << string
57
+ end
58
+
59
+ alias_method :on_cdata_block, :on_characters
60
+ end
61
+
62
+ attr_accessor :document_class
63
+ self.document_class = HashBuilder
64
+
65
+ def parse(data)
66
+ if !data.respond_to?(:read)
67
+ data = StringIO.new(data || "")
68
+ end
69
+
70
+ if data.eof?
71
+ {}
72
+ else
73
+ LibXML::XML::Error.set_handler(&LibXML::XML::Error::QUIET_HANDLER)
74
+ parser = LibXML::XML::SaxParser.io(data)
75
+ document = document_class.new
76
+
77
+ parser.callbacks = document
78
+ parser.parse
79
+ document.hash
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ begin
4
+ require "nokogiri"
5
+ rescue LoadError => e
6
+ warn "You don't have nokogiri installed in your application. Please add it to your Gemfile and run bundle install"
7
+ raise e
8
+ end
9
+ require "active_support/core_ext/object/blank"
10
+ require "stringio"
11
+
12
+ module ActiveSupport
13
+ module XmlMini_Nokogiri # :nodoc:
14
+ extend self
15
+
16
+ # Parse an XML Document string or IO into a simple hash using libxml / nokogiri.
17
+ # data::
18
+ # XML Document string or IO to parse
19
+ def parse(data)
20
+ if !data.respond_to?(:read)
21
+ data = StringIO.new(data || "")
22
+ end
23
+
24
+ if data.eof?
25
+ {}
26
+ else
27
+ doc = Nokogiri::XML(data)
28
+ raise doc.errors.first if doc.errors.length > 0
29
+ doc.to_hash
30
+ end
31
+ end
32
+
33
+ module Conversions # :nodoc:
34
+ module Document # :nodoc:
35
+ def to_hash
36
+ root.to_hash
37
+ end
38
+ end
39
+
40
+ module Node # :nodoc:
41
+ CONTENT_ROOT = "__content__"
42
+
43
+ # Convert XML document to hash.
44
+ #
45
+ # hash::
46
+ # Hash to merge the converted element into.
47
+ def to_hash(hash = {})
48
+ node_hash = {}
49
+
50
+ # Insert node hash into parent hash correctly.
51
+ case hash[name]
52
+ when Array then hash[name] << node_hash
53
+ when Hash then hash[name] = [hash[name], node_hash]
54
+ when nil then hash[name] = node_hash
55
+ end
56
+
57
+ # Handle child elements
58
+ children.each do |c|
59
+ if c.element?
60
+ c.to_hash(node_hash)
61
+ elsif c.text? || c.cdata?
62
+ node_hash[CONTENT_ROOT] ||= +""
63
+ node_hash[CONTENT_ROOT] << c.content
64
+ end
65
+ end
66
+
67
+ # Remove content node if it is blank and there are child tags
68
+ if node_hash.length > 1 && node_hash[CONTENT_ROOT].blank?
69
+ node_hash.delete(CONTENT_ROOT)
70
+ end
71
+
72
+ # Handle attributes
73
+ attribute_nodes.each { |a| node_hash[a.node_name] = a.value }
74
+
75
+ hash
76
+ end
77
+ end
78
+ end
79
+
80
+ Nokogiri::XML::Document.include(Conversions::Document)
81
+ Nokogiri::XML::Node.include(Conversions::Node)
82
+ end
83
+ end
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ begin
4
+ require "nokogiri"
5
+ rescue LoadError => e
6
+ warn "You don't have nokogiri installed in your application. Please add it to your Gemfile and run bundle install"
7
+ raise e
8
+ end
9
+ require "active_support/core_ext/object/blank"
10
+ require "stringio"
11
+
12
+ module ActiveSupport
13
+ module XmlMini_NokogiriSAX # :nodoc:
14
+ extend self
15
+
16
+ # Class that will build the hash while the XML document
17
+ # is being parsed using SAX events.
18
+ class HashBuilder < Nokogiri::XML::SAX::Document
19
+ CONTENT_KEY = "__content__"
20
+ HASH_SIZE_KEY = "__hash_size__"
21
+
22
+ attr_reader :hash
23
+
24
+ def current_hash
25
+ @hash_stack.last
26
+ end
27
+
28
+ def start_document
29
+ @hash = {}
30
+ @hash_stack = [@hash]
31
+ end
32
+
33
+ def end_document
34
+ raise "Parse stack not empty!" if @hash_stack.size > 1
35
+ end
36
+
37
+ def error(error_message)
38
+ raise error_message
39
+ end
40
+
41
+ def start_element(name, attrs = [])
42
+ new_hash = { CONTENT_KEY => +"" }.merge!(Hash[attrs])
43
+ new_hash[HASH_SIZE_KEY] = new_hash.size + 1
44
+
45
+ case current_hash[name]
46
+ when Array then current_hash[name] << new_hash
47
+ when Hash then current_hash[name] = [current_hash[name], new_hash]
48
+ when nil then current_hash[name] = new_hash
49
+ end
50
+
51
+ @hash_stack.push(new_hash)
52
+ end
53
+
54
+ def end_element(name)
55
+ if current_hash.length > current_hash.delete(HASH_SIZE_KEY) && current_hash[CONTENT_KEY].blank? || current_hash[CONTENT_KEY] == ""
56
+ current_hash.delete(CONTENT_KEY)
57
+ end
58
+ @hash_stack.pop
59
+ end
60
+
61
+ def characters(string)
62
+ current_hash[CONTENT_KEY] << string
63
+ end
64
+
65
+ alias_method :cdata_block, :characters
66
+ end
67
+
68
+ attr_accessor :document_class
69
+ self.document_class = HashBuilder
70
+
71
+ def parse(data)
72
+ if !data.respond_to?(:read)
73
+ data = StringIO.new(data || "")
74
+ end
75
+
76
+ if data.eof?
77
+ {}
78
+ else
79
+ document = document_class.new
80
+ parser = Nokogiri::XML::SAX::Parser.new(document)
81
+ parser.parse(data)
82
+ document.hash
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,137 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/kernel/reporting"
4
+ require "active_support/core_ext/object/blank"
5
+ require "stringio"
6
+
7
+ module ActiveSupport
8
+ module XmlMini_REXML # :nodoc:
9
+ extend self
10
+
11
+ CONTENT_KEY = "__content__"
12
+
13
+ # Parse an XML Document string or IO into a simple hash.
14
+ #
15
+ # Same as XmlSimple::xml_in but doesn't shoot itself in the foot,
16
+ # and uses the defaults from Active Support.
17
+ #
18
+ # data::
19
+ # XML Document string or IO to parse
20
+ def parse(data)
21
+ if !data.respond_to?(:read)
22
+ data = StringIO.new(data || "")
23
+ end
24
+
25
+ if data.eof?
26
+ {}
27
+ else
28
+ require_rexml unless defined?(REXML::Document)
29
+ doc = REXML::Document.new(data)
30
+
31
+ if doc.root
32
+ merge_element!({}, doc.root, XmlMini.depth)
33
+ else
34
+ raise REXML::ParseException,
35
+ "The document #{doc.to_s.inspect} does not have a valid root"
36
+ end
37
+ end
38
+ end
39
+
40
+ private
41
+ def require_rexml
42
+ silence_warnings { require "rexml/document" }
43
+ rescue LoadError => e
44
+ warn "You don't have rexml installed in your application. Please add it to your Gemfile and run bundle install"
45
+ raise e
46
+ end
47
+
48
+ # Convert an XML element and merge into the hash
49
+ #
50
+ # hash::
51
+ # Hash to merge the converted element into.
52
+ # element::
53
+ # XML element to merge into hash
54
+ def merge_element!(hash, element, depth)
55
+ raise REXML::ParseException, "The document is too deep" if depth == 0
56
+ merge!(hash, element.name, collapse(element, depth))
57
+ end
58
+
59
+ # Actually converts an XML document element into a data structure.
60
+ #
61
+ # element::
62
+ # The document element to be collapsed.
63
+ def collapse(element, depth)
64
+ hash = get_attributes(element)
65
+
66
+ if element.has_elements?
67
+ element.each_element { |child| merge_element!(hash, child, depth - 1) }
68
+ merge_texts!(hash, element) unless empty_content?(element)
69
+ hash
70
+ else
71
+ merge_texts!(hash, element)
72
+ end
73
+ end
74
+
75
+ # Merge all the texts of an element into the hash
76
+ #
77
+ # hash::
78
+ # Hash to add the converted element to.
79
+ # element::
80
+ # XML element whose texts are to me merged into the hash
81
+ def merge_texts!(hash, element)
82
+ unless element.has_text?
83
+ hash
84
+ else
85
+ # must use value to prevent double-escaping
86
+ texts = +""
87
+ element.texts.each { |t| texts << t.value }
88
+ merge!(hash, CONTENT_KEY, texts)
89
+ end
90
+ end
91
+
92
+ # Adds a new key/value pair to an existing Hash. If the key to be added
93
+ # already exists and the existing value associated with key is not
94
+ # an Array, it will be wrapped in an Array. Then the new value is
95
+ # appended to that Array.
96
+ #
97
+ # hash::
98
+ # Hash to add key/value pair to.
99
+ # key::
100
+ # Key to be added.
101
+ # value::
102
+ # Value to be associated with key.
103
+ def merge!(hash, key, value)
104
+ if hash.has_key?(key)
105
+ if hash[key].instance_of?(Array)
106
+ hash[key] << value
107
+ else
108
+ hash[key] = [hash[key], value]
109
+ end
110
+ elsif value.instance_of?(Array)
111
+ hash[key] = [value]
112
+ else
113
+ hash[key] = value
114
+ end
115
+ hash
116
+ end
117
+
118
+ # Converts the attributes array of an XML element into a hash.
119
+ # Returns an empty Hash if node has no attributes.
120
+ #
121
+ # element::
122
+ # XML element to extract attributes from.
123
+ def get_attributes(element)
124
+ attributes = {}
125
+ element.attributes.each { |n, v| attributes[n] = v }
126
+ attributes
127
+ end
128
+
129
+ # Determines if a document element has text content
130
+ #
131
+ # element::
132
+ # XML element to be checked.
133
+ def empty_content?(element)
134
+ element.texts.join.blank?
135
+ end
136
+ end
137
+ end