activesupport 5.1.7 → 6.1.7

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 (262) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +434 -490
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +6 -5
  5. data/lib/active_support/actionable_error.rb +48 -0
  6. data/lib/active_support/all.rb +2 -0
  7. data/lib/active_support/array_inquirer.rb +6 -2
  8. data/lib/active_support/backtrace_cleaner.rb +31 -3
  9. data/lib/active_support/benchmarkable.rb +3 -1
  10. data/lib/active_support/builder.rb +2 -0
  11. data/lib/active_support/cache/file_store.rb +37 -36
  12. data/lib/active_support/cache/mem_cache_store.rb +72 -56
  13. data/lib/active_support/cache/memory_store.rb +61 -33
  14. data/lib/active_support/cache/null_store.rb +10 -3
  15. data/lib/active_support/cache/redis_cache_store.rb +493 -0
  16. data/lib/active_support/cache/strategy/local_cache.rb +67 -21
  17. data/lib/active_support/cache/strategy/local_cache_middleware.rb +2 -0
  18. data/lib/active_support/cache.rb +310 -126
  19. data/lib/active_support/callbacks.rb +106 -100
  20. data/lib/active_support/concern.rb +79 -6
  21. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +18 -0
  22. data/lib/active_support/concurrency/share_lock.rb +2 -1
  23. data/lib/active_support/configurable.rb +12 -14
  24. data/lib/active_support/configuration_file.rb +51 -0
  25. data/lib/active_support/core_ext/array/access.rb +21 -7
  26. data/lib/active_support/core_ext/array/conversions.rb +7 -5
  27. data/lib/active_support/core_ext/array/extract.rb +21 -0
  28. data/lib/active_support/core_ext/array/extract_options.rb +2 -0
  29. data/lib/active_support/core_ext/array/grouping.rb +2 -0
  30. data/lib/active_support/core_ext/array/inquiry.rb +2 -0
  31. data/lib/active_support/core_ext/array/wrap.rb +2 -0
  32. data/lib/active_support/core_ext/array.rb +3 -1
  33. data/lib/active_support/core_ext/benchmark.rb +4 -2
  34. data/lib/active_support/core_ext/big_decimal/conversions.rb +2 -0
  35. data/lib/active_support/core_ext/big_decimal.rb +2 -0
  36. data/lib/active_support/core_ext/class/attribute.rb +50 -47
  37. data/lib/active_support/core_ext/class/attribute_accessors.rb +2 -0
  38. data/lib/active_support/core_ext/class/subclasses.rb +18 -40
  39. data/lib/active_support/core_ext/class.rb +2 -0
  40. data/lib/active_support/core_ext/date/acts_like.rb +2 -0
  41. data/lib/active_support/core_ext/date/blank.rb +2 -0
  42. data/lib/active_support/core_ext/date/calculations.rb +8 -5
  43. data/lib/active_support/core_ext/date/conversions.rb +12 -10
  44. data/lib/active_support/core_ext/date/zones.rb +2 -0
  45. data/lib/active_support/core_ext/date.rb +2 -0
  46. data/lib/active_support/core_ext/date_and_time/calculations.rb +61 -37
  47. data/lib/active_support/core_ext/date_and_time/compatibility.rb +18 -1
  48. data/lib/active_support/core_ext/date_and_time/zones.rb +2 -1
  49. data/lib/active_support/core_ext/date_time/acts_like.rb +2 -0
  50. data/lib/active_support/core_ext/date_time/blank.rb +2 -0
  51. data/lib/active_support/core_ext/date_time/calculations.rb +3 -1
  52. data/lib/active_support/core_ext/date_time/compatibility.rb +7 -5
  53. data/lib/active_support/core_ext/date_time/conversions.rb +2 -1
  54. data/lib/active_support/core_ext/date_time.rb +2 -0
  55. data/lib/active_support/core_ext/digest/uuid.rb +4 -1
  56. data/lib/active_support/core_ext/digest.rb +3 -0
  57. data/lib/active_support/core_ext/enumerable.rb +174 -71
  58. data/lib/active_support/core_ext/file/atomic.rb +3 -1
  59. data/lib/active_support/core_ext/file.rb +2 -0
  60. data/lib/active_support/core_ext/hash/conversions.rb +7 -5
  61. data/lib/active_support/core_ext/hash/deep_merge.rb +8 -12
  62. data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
  63. data/lib/active_support/core_ext/hash/except.rb +4 -2
  64. data/lib/active_support/core_ext/hash/indifferent_access.rb +2 -0
  65. data/lib/active_support/core_ext/hash/keys.rb +3 -30
  66. data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
  67. data/lib/active_support/core_ext/hash/slice.rb +8 -29
  68. data/lib/active_support/core_ext/hash.rb +3 -2
  69. data/lib/active_support/core_ext/integer/inflections.rb +2 -0
  70. data/lib/active_support/core_ext/integer/multiple.rb +3 -1
  71. data/lib/active_support/core_ext/integer/time.rb +7 -14
  72. data/lib/active_support/core_ext/integer.rb +2 -0
  73. data/lib/active_support/core_ext/kernel/concern.rb +2 -0
  74. data/lib/active_support/core_ext/kernel/reporting.rb +2 -0
  75. data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
  76. data/lib/active_support/core_ext/kernel.rb +2 -1
  77. data/lib/active_support/core_ext/load_error.rb +3 -8
  78. data/lib/active_support/core_ext/marshal.rb +4 -0
  79. data/lib/active_support/core_ext/module/aliasing.rb +2 -0
  80. data/lib/active_support/core_ext/module/anonymous.rb +2 -0
  81. data/lib/active_support/core_ext/module/attr_internal.rb +4 -2
  82. data/lib/active_support/core_ext/module/attribute_accessors.rb +44 -56
  83. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +18 -18
  84. data/lib/active_support/core_ext/module/concerning.rb +15 -10
  85. data/lib/active_support/core_ext/module/delegation.rb +103 -58
  86. data/lib/active_support/core_ext/module/deprecation.rb +2 -0
  87. data/lib/active_support/core_ext/module/introspection.rb +18 -15
  88. data/lib/active_support/core_ext/module/redefine_method.rb +40 -0
  89. data/lib/active_support/core_ext/module/remove_method.rb +5 -23
  90. data/lib/active_support/core_ext/module.rb +3 -1
  91. data/lib/active_support/core_ext/name_error.rb +36 -2
  92. data/lib/active_support/core_ext/numeric/bytes.rb +2 -0
  93. data/lib/active_support/core_ext/numeric/conversions.rb +131 -129
  94. data/lib/active_support/core_ext/numeric/time.rb +7 -15
  95. data/lib/active_support/core_ext/numeric.rb +2 -1
  96. data/lib/active_support/core_ext/object/acts_like.rb +12 -1
  97. data/lib/active_support/core_ext/object/blank.rb +13 -3
  98. data/lib/active_support/core_ext/object/conversions.rb +2 -0
  99. data/lib/active_support/core_ext/object/deep_dup.rb +3 -1
  100. data/lib/active_support/core_ext/object/duplicable.rb +9 -114
  101. data/lib/active_support/core_ext/object/inclusion.rb +2 -0
  102. data/lib/active_support/core_ext/object/instance_variables.rb +2 -0
  103. data/lib/active_support/core_ext/object/json.rb +22 -2
  104. data/lib/active_support/core_ext/object/to_param.rb +2 -0
  105. data/lib/active_support/core_ext/object/to_query.rb +2 -0
  106. data/lib/active_support/core_ext/object/try.rb +19 -7
  107. data/lib/active_support/core_ext/object/with_options.rb +4 -2
  108. data/lib/active_support/core_ext/object.rb +2 -0
  109. data/lib/active_support/core_ext/range/compare_range.rb +82 -0
  110. data/lib/active_support/core_ext/range/conversions.rb +35 -25
  111. data/lib/active_support/core_ext/range/each.rb +5 -2
  112. data/lib/active_support/core_ext/range/include_time_with_zone.rb +28 -0
  113. data/lib/active_support/core_ext/range/overlaps.rb +2 -0
  114. data/lib/active_support/core_ext/range.rb +4 -1
  115. data/lib/active_support/core_ext/regexp.rb +10 -5
  116. data/lib/active_support/core_ext/securerandom.rb +25 -3
  117. data/lib/active_support/core_ext/string/access.rb +7 -16
  118. data/lib/active_support/core_ext/string/behavior.rb +2 -0
  119. data/lib/active_support/core_ext/string/conversions.rb +3 -0
  120. data/lib/active_support/core_ext/string/exclude.rb +2 -0
  121. data/lib/active_support/core_ext/string/filters.rb +44 -1
  122. data/lib/active_support/core_ext/string/indent.rb +2 -0
  123. data/lib/active_support/core_ext/string/inflections.rb +69 -16
  124. data/lib/active_support/core_ext/string/inquiry.rb +3 -0
  125. data/lib/active_support/core_ext/string/multibyte.rb +9 -4
  126. data/lib/active_support/core_ext/string/output_safety.rb +104 -20
  127. data/lib/active_support/core_ext/string/starts_ends_with.rb +4 -2
  128. data/lib/active_support/core_ext/string/strip.rb +5 -1
  129. data/lib/active_support/core_ext/string/zones.rb +2 -0
  130. data/lib/active_support/core_ext/string.rb +2 -0
  131. data/lib/active_support/core_ext/symbol/starts_ends_with.rb +14 -0
  132. data/lib/active_support/core_ext/symbol.rb +3 -0
  133. data/lib/active_support/core_ext/time/acts_like.rb +2 -0
  134. data/lib/active_support/core_ext/time/calculations.rb +76 -18
  135. data/lib/active_support/core_ext/time/compatibility.rb +4 -2
  136. data/lib/active_support/core_ext/time/conversions.rb +4 -0
  137. data/lib/active_support/core_ext/time/zones.rb +6 -4
  138. data/lib/active_support/core_ext/time.rb +2 -0
  139. data/lib/active_support/core_ext/uri.rb +11 -6
  140. data/lib/active_support/core_ext.rb +3 -1
  141. data/lib/active_support/current_attributes/test_helper.rb +13 -0
  142. data/lib/active_support/current_attributes.rb +210 -0
  143. data/lib/active_support/dependencies/autoload.rb +2 -0
  144. data/lib/active_support/dependencies/interlock.rb +2 -0
  145. data/lib/active_support/dependencies/zeitwerk_integration.rb +120 -0
  146. data/lib/active_support/dependencies.rb +134 -60
  147. data/lib/active_support/deprecation/behaviors.rb +43 -11
  148. data/lib/active_support/deprecation/constant_accessor.rb +4 -2
  149. data/lib/active_support/deprecation/disallowed.rb +56 -0
  150. data/lib/active_support/deprecation/instance_delegator.rb +2 -1
  151. data/lib/active_support/deprecation/method_wrappers.rb +29 -21
  152. data/lib/active_support/deprecation/proxy_wrappers.rb +32 -6
  153. data/lib/active_support/deprecation/reporting.rb +54 -9
  154. data/lib/active_support/deprecation.rb +9 -2
  155. data/lib/active_support/descendants_tracker.rb +61 -9
  156. data/lib/active_support/digest.rb +22 -0
  157. data/lib/active_support/duration/iso8601_parser.rb +6 -6
  158. data/lib/active_support/duration/iso8601_serializer.rb +20 -14
  159. data/lib/active_support/duration.rb +102 -45
  160. data/lib/active_support/encrypted_configuration.rb +45 -0
  161. data/lib/active_support/encrypted_file.rb +117 -0
  162. data/lib/active_support/environment_inquirer.rb +20 -0
  163. data/lib/active_support/evented_file_update_checker.rb +84 -117
  164. data/lib/active_support/execution_wrapper.rb +19 -13
  165. data/lib/active_support/executor.rb +2 -0
  166. data/lib/active_support/file_update_checker.rb +2 -1
  167. data/lib/active_support/fork_tracker.rb +64 -0
  168. data/lib/active_support/gem_version.rb +3 -1
  169. data/lib/active_support/gzip.rb +2 -0
  170. data/lib/active_support/hash_with_indifferent_access.rb +123 -41
  171. data/lib/active_support/i18n.rb +4 -1
  172. data/lib/active_support/i18n_railtie.rb +19 -14
  173. data/lib/active_support/inflections.rb +2 -0
  174. data/lib/active_support/inflector/inflections.rb +19 -8
  175. data/lib/active_support/inflector/methods.rb +87 -77
  176. data/lib/active_support/inflector/transliterate.rb +56 -18
  177. data/lib/active_support/inflector.rb +2 -0
  178. data/lib/active_support/json/decoding.rb +27 -26
  179. data/lib/active_support/json/encoding.rb +13 -3
  180. data/lib/active_support/json.rb +2 -0
  181. data/lib/active_support/key_generator.rb +3 -33
  182. data/lib/active_support/lazy_load_hooks.rb +7 -2
  183. data/lib/active_support/locale/en.rb +33 -0
  184. data/lib/active_support/locale/en.yml +7 -3
  185. data/lib/active_support/log_subscriber/test_helper.rb +2 -0
  186. data/lib/active_support/log_subscriber.rb +42 -11
  187. data/lib/active_support/logger.rb +4 -17
  188. data/lib/active_support/logger_silence.rb +13 -20
  189. data/lib/active_support/logger_thread_safe_level.rb +54 -7
  190. data/lib/active_support/message_encryptor.rb +100 -32
  191. data/lib/active_support/message_verifier.rb +85 -14
  192. data/lib/active_support/messages/metadata.rb +80 -0
  193. data/lib/active_support/messages/rotation_configuration.rb +23 -0
  194. data/lib/active_support/messages/rotator.rb +57 -0
  195. data/lib/active_support/multibyte/chars.rb +12 -68
  196. data/lib/active_support/multibyte/unicode.rb +17 -327
  197. data/lib/active_support/multibyte.rb +2 -0
  198. data/lib/active_support/notifications/fanout.rb +118 -16
  199. data/lib/active_support/notifications/instrumenter.rb +73 -9
  200. data/lib/active_support/notifications.rb +74 -8
  201. data/lib/active_support/number_helper/number_converter.rb +7 -6
  202. data/lib/active_support/number_helper/number_to_currency_converter.rb +6 -9
  203. data/lib/active_support/number_helper/number_to_delimited_converter.rb +5 -2
  204. data/lib/active_support/number_helper/number_to_human_converter.rb +6 -3
  205. data/lib/active_support/number_helper/number_to_human_size_converter.rb +6 -3
  206. data/lib/active_support/number_helper/number_to_percentage_converter.rb +5 -1
  207. data/lib/active_support/number_helper/number_to_phone_converter.rb +5 -2
  208. data/lib/active_support/number_helper/number_to_rounded_converter.rb +14 -27
  209. data/lib/active_support/number_helper/rounding_helper.rb +16 -30
  210. data/lib/active_support/number_helper.rb +40 -12
  211. data/lib/active_support/option_merger.rb +24 -3
  212. data/lib/active_support/ordered_hash.rb +3 -1
  213. data/lib/active_support/ordered_options.rb +17 -5
  214. data/lib/active_support/parameter_filter.rb +133 -0
  215. data/lib/active_support/per_thread_registry.rb +4 -1
  216. data/lib/active_support/proxy_object.rb +2 -0
  217. data/lib/active_support/rails.rb +3 -10
  218. data/lib/active_support/railtie.rb +60 -9
  219. data/lib/active_support/reloader.rb +12 -11
  220. data/lib/active_support/rescuable.rb +7 -6
  221. data/lib/active_support/secure_compare_rotator.rb +51 -0
  222. data/lib/active_support/security_utils.rb +26 -15
  223. data/lib/active_support/string_inquirer.rb +6 -3
  224. data/lib/active_support/subscriber.rb +74 -24
  225. data/lib/active_support/tagged_logging.rb +44 -8
  226. data/lib/active_support/test_case.rb +94 -2
  227. data/lib/active_support/testing/assertions.rb +58 -20
  228. data/lib/active_support/testing/autorun.rb +2 -0
  229. data/lib/active_support/testing/constant_lookup.rb +2 -0
  230. data/lib/active_support/testing/declarative.rb +2 -0
  231. data/lib/active_support/testing/deprecation.rb +2 -1
  232. data/lib/active_support/testing/file_fixtures.rb +4 -0
  233. data/lib/active_support/testing/isolation.rb +4 -2
  234. data/lib/active_support/testing/method_call_assertions.rb +30 -1
  235. data/lib/active_support/testing/parallelization/server.rb +78 -0
  236. data/lib/active_support/testing/parallelization/worker.rb +100 -0
  237. data/lib/active_support/testing/parallelization.rb +51 -0
  238. data/lib/active_support/testing/setup_and_teardown.rb +12 -7
  239. data/lib/active_support/testing/stream.rb +3 -2
  240. data/lib/active_support/testing/tagged_logging.rb +2 -0
  241. data/lib/active_support/testing/time_helpers.rb +78 -13
  242. data/lib/active_support/time.rb +2 -0
  243. data/lib/active_support/time_with_zone.rb +113 -41
  244. data/lib/active_support/values/time_zone.rb +54 -25
  245. data/lib/active_support/version.rb +2 -0
  246. data/lib/active_support/xml_mini/jdom.rb +5 -4
  247. data/lib/active_support/xml_mini/libxml.rb +4 -2
  248. data/lib/active_support/xml_mini/libxmlsax.rb +6 -4
  249. data/lib/active_support/xml_mini/nokogiri.rb +4 -2
  250. data/lib/active_support/xml_mini/nokogirisax.rb +5 -3
  251. data/lib/active_support/xml_mini/rexml.rb +12 -3
  252. data/lib/active_support/xml_mini.rb +5 -11
  253. data/lib/active_support.rb +18 -13
  254. metadata +71 -32
  255. data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -7
  256. data/lib/active_support/core_ext/hash/compact.rb +0 -27
  257. data/lib/active_support/core_ext/hash/transform_values.rb +0 -30
  258. data/lib/active_support/core_ext/kernel/agnostics.rb +0 -11
  259. data/lib/active_support/core_ext/module/reachable.rb +0 -8
  260. data/lib/active_support/core_ext/numeric/inquiry.rb +0 -26
  261. data/lib/active_support/core_ext/range/include_range.rb +0 -23
  262. data/lib/active_support/values/unicode_tables.dat +0 -0
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/inflector/methods"
2
4
  require "active_support/inflector/transliterate"
3
5
 
@@ -28,6 +30,8 @@ class String
28
30
  # 'apple'.pluralize(2) # => "apples"
29
31
  # 'ley'.pluralize(:es) # => "leyes"
30
32
  # 'ley'.pluralize(1, :es) # => "ley"
33
+ #
34
+ # See ActiveSupport::Inflector.pluralize.
31
35
  def pluralize(count = nil, locale = :en)
32
36
  locale = count if count.is_a?(Symbol)
33
37
  if count == 1
@@ -51,28 +55,34 @@ class String
51
55
  # 'the blue mailmen'.singularize # => "the blue mailman"
52
56
  # 'CamelOctopi'.singularize # => "CamelOctopus"
53
57
  # 'leyes'.singularize(:es) # => "ley"
58
+ #
59
+ # See ActiveSupport::Inflector.singularize.
54
60
  def singularize(locale = :en)
55
61
  ActiveSupport::Inflector.singularize(self, locale)
56
62
  end
57
63
 
58
64
  # +constantize+ tries to find a declared constant with the name specified
59
65
  # in the string. It raises a NameError when the name is not in CamelCase
60
- # or is not initialized. See ActiveSupport::Inflector.constantize
66
+ # or is not initialized.
61
67
  #
62
68
  # 'Module'.constantize # => Module
63
69
  # 'Class'.constantize # => Class
64
70
  # 'blargle'.constantize # => NameError: wrong constant name blargle
71
+ #
72
+ # See ActiveSupport::Inflector.constantize.
65
73
  def constantize
66
74
  ActiveSupport::Inflector.constantize(self)
67
75
  end
68
76
 
69
77
  # +safe_constantize+ tries to find a declared constant with the name specified
70
78
  # in the string. It returns +nil+ when the name is not in CamelCase
71
- # or is not initialized. See ActiveSupport::Inflector.safe_constantize
79
+ # or is not initialized.
72
80
  #
73
81
  # 'Module'.safe_constantize # => Module
74
82
  # 'Class'.safe_constantize # => Class
75
83
  # 'blargle'.safe_constantize # => nil
84
+ #
85
+ # See ActiveSupport::Inflector.safe_constantize.
76
86
  def safe_constantize
77
87
  ActiveSupport::Inflector.safe_constantize(self)
78
88
  end
@@ -86,12 +96,18 @@ class String
86
96
  # 'active_record'.camelize(:lower) # => "activeRecord"
87
97
  # 'active_record/errors'.camelize # => "ActiveRecord::Errors"
88
98
  # 'active_record/errors'.camelize(:lower) # => "activeRecord::Errors"
99
+ #
100
+ # +camelize+ is also aliased as +camelcase+.
101
+ #
102
+ # See ActiveSupport::Inflector.camelize.
89
103
  def camelize(first_letter = :upper)
90
104
  case first_letter
91
105
  when :upper
92
106
  ActiveSupport::Inflector.camelize(self, true)
93
107
  when :lower
94
108
  ActiveSupport::Inflector.camelize(self, false)
109
+ else
110
+ raise ArgumentError, "Invalid option, use either :upper or :lower."
95
111
  end
96
112
  end
97
113
  alias_method :camelcase, :camelize
@@ -100,12 +116,19 @@ class String
100
116
  # a nicer looking title. +titleize+ is meant for creating pretty output. It is not
101
117
  # used in the Rails internals.
102
118
  #
119
+ # The trailing '_id','Id'.. can be kept and capitalized by setting the
120
+ # optional parameter +keep_id_suffix+ to true.
121
+ # By default, this parameter is false.
122
+ #
123
+ # 'man from the boondocks'.titleize # => "Man From The Boondocks"
124
+ # 'x-men: the last stand'.titleize # => "X Men: The Last Stand"
125
+ # 'string_ending_with_id'.titleize(keep_id_suffix: true) # => "String Ending With Id"
126
+ #
103
127
  # +titleize+ is also aliased as +titlecase+.
104
128
  #
105
- # 'man from the boondocks'.titleize # => "Man From The Boondocks"
106
- # 'x-men: the last stand'.titleize # => "X Men: The Last Stand"
107
- def titleize
108
- ActiveSupport::Inflector.titleize(self)
129
+ # See ActiveSupport::Inflector.titleize.
130
+ def titleize(keep_id_suffix: false)
131
+ ActiveSupport::Inflector.titleize(self, keep_id_suffix: keep_id_suffix)
109
132
  end
110
133
  alias_method :titlecase, :titleize
111
134
 
@@ -115,6 +138,8 @@ class String
115
138
  #
116
139
  # 'ActiveModel'.underscore # => "active_model"
117
140
  # 'ActiveModel::Errors'.underscore # => "active_model/errors"
141
+ #
142
+ # See ActiveSupport::Inflector.underscore.
118
143
  def underscore
119
144
  ActiveSupport::Inflector.underscore(self)
120
145
  end
@@ -122,6 +147,8 @@ class String
122
147
  # Replaces underscores with dashes in the string.
123
148
  #
124
149
  # 'puni_puni'.dasherize # => "puni-puni"
150
+ #
151
+ # See ActiveSupport::Inflector.dasherize.
125
152
  def dasherize
126
153
  ActiveSupport::Inflector.dasherize(self)
127
154
  end
@@ -133,6 +160,8 @@ class String
133
160
  # '::Inflections'.demodulize # => "Inflections"
134
161
  # ''.demodulize # => ''
135
162
  #
163
+ # See ActiveSupport::Inflector.demodulize.
164
+ #
136
165
  # See also +deconstantize+.
137
166
  def demodulize
138
167
  ActiveSupport::Inflector.demodulize(self)
@@ -146,6 +175,8 @@ class String
146
175
  # '::String'.deconstantize # => ""
147
176
  # ''.deconstantize # => ""
148
177
  #
178
+ # See ActiveSupport::Inflector.deconstantize.
179
+ #
149
180
  # See also +demodulize+.
150
181
  def deconstantize
151
182
  ActiveSupport::Inflector.deconstantize(self)
@@ -153,6 +184,11 @@ class String
153
184
 
154
185
  # Replaces special characters in a string so that it may be used as part of a 'pretty' URL.
155
186
  #
187
+ # If the optional parameter +locale+ is specified,
188
+ # the word will be parameterized as a word of that language.
189
+ # By default, this parameter is set to <tt>nil</tt> and it will use
190
+ # the configured <tt>I18n.locale</tt>.
191
+ #
156
192
  # class Person
157
193
  # def to_param
158
194
  # "#{id}-#{name.parameterize}"
@@ -165,7 +201,7 @@ class String
165
201
  # <%= link_to(@person.name, person_path) %>
166
202
  # # => <a href="/person/1-donald-e-knuth">Donald E. Knuth</a>
167
203
  #
168
- # To preserve the case of the characters in a string, use the `preserve_case` argument.
204
+ # To preserve the case of the characters in a string, use the +preserve_case+ argument.
169
205
  #
170
206
  # class Person
171
207
  # def to_param
@@ -178,8 +214,10 @@ class String
178
214
  #
179
215
  # <%= link_to(@person.name, person_path) %>
180
216
  # # => <a href="/person/1-Donald-E-Knuth">Donald E. Knuth</a>
181
- def parameterize(separator: "-", preserve_case: false)
182
- ActiveSupport::Inflector.parameterize(self, separator: separator, preserve_case: preserve_case)
217
+ #
218
+ # See ActiveSupport::Inflector.parameterize.
219
+ def parameterize(separator: "-", preserve_case: false, locale: nil)
220
+ ActiveSupport::Inflector.parameterize(self, separator: separator, preserve_case: preserve_case, locale: locale)
183
221
  end
184
222
 
185
223
  # Creates the name of a table like Rails does for models to table names. This method
@@ -188,6 +226,8 @@ class String
188
226
  # 'RawScaledScorer'.tableize # => "raw_scaled_scorers"
189
227
  # 'ham_and_egg'.tableize # => "ham_and_eggs"
190
228
  # 'fancyCategory'.tableize # => "fancy_categories"
229
+ #
230
+ # See ActiveSupport::Inflector.tableize.
191
231
  def tableize
192
232
  ActiveSupport::Inflector.tableize(self)
193
233
  end
@@ -198,11 +238,13 @@ class String
198
238
  #
199
239
  # 'ham_and_eggs'.classify # => "HamAndEgg"
200
240
  # 'posts'.classify # => "Post"
241
+ #
242
+ # See ActiveSupport::Inflector.classify.
201
243
  def classify
202
244
  ActiveSupport::Inflector.classify(self)
203
245
  end
204
246
 
205
- # Capitalizes the first word, turns underscores into spaces, and strips a
247
+ # Capitalizes the first word, turns underscores into spaces, and (by default)strips a
206
248
  # trailing '_id' if present.
207
249
  # Like +titleize+, this is meant for creating pretty output.
208
250
  #
@@ -210,12 +252,19 @@ class String
210
252
  # optional parameter +capitalize+ to false.
211
253
  # By default, this parameter is true.
212
254
  #
213
- # 'employee_salary'.humanize # => "Employee salary"
214
- # 'author_id'.humanize # => "Author"
215
- # 'author_id'.humanize(capitalize: false) # => "author"
216
- # '_id'.humanize # => "Id"
217
- def humanize(options = {})
218
- ActiveSupport::Inflector.humanize(self, options)
255
+ # The trailing '_id' can be kept and capitalized by setting the
256
+ # optional parameter +keep_id_suffix+ to true.
257
+ # By default, this parameter is false.
258
+ #
259
+ # 'employee_salary'.humanize # => "Employee salary"
260
+ # 'author_id'.humanize # => "Author"
261
+ # 'author_id'.humanize(capitalize: false) # => "author"
262
+ # '_id'.humanize # => "Id"
263
+ # 'author_id'.humanize(keep_id_suffix: true) # => "Author Id"
264
+ #
265
+ # See ActiveSupport::Inflector.humanize.
266
+ def humanize(capitalize: true, keep_id_suffix: false)
267
+ ActiveSupport::Inflector.humanize(self, capitalize: capitalize, keep_id_suffix: keep_id_suffix)
219
268
  end
220
269
 
221
270
  # Converts just the first character to uppercase.
@@ -223,6 +272,8 @@ class String
223
272
  # 'what a Lovely Day'.upcase_first # => "What a Lovely Day"
224
273
  # 'w'.upcase_first # => "W"
225
274
  # ''.upcase_first # => ""
275
+ #
276
+ # See ActiveSupport::Inflector.upcase_first.
226
277
  def upcase_first
227
278
  ActiveSupport::Inflector.upcase_first(self)
228
279
  end
@@ -234,6 +285,8 @@ class String
234
285
  # 'Message'.foreign_key # => "message_id"
235
286
  # 'Message'.foreign_key(false) # => "messageid"
236
287
  # 'Admin::Post'.foreign_key # => "post_id"
288
+ #
289
+ # See ActiveSupport::Inflector.foreign_key.
237
290
  def foreign_key(separate_class_name_and_id_with_underscore = true)
238
291
  ActiveSupport::Inflector.foreign_key(self, separate_class_name_and_id_with_underscore)
239
292
  end
@@ -1,4 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/string_inquirer"
4
+ require "active_support/environment_inquirer"
2
5
 
3
6
  class String
4
7
  # Wraps the current string in the <tt>ActiveSupport::StringInquirer</tt> class,
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/multibyte"
2
4
 
3
5
  class String
@@ -9,11 +11,14 @@ class String
9
11
  # encapsulates the original string. A Unicode safe version of all the String methods are defined on this proxy
10
12
  # class. If the proxy class doesn't respond to a certain method, it's forwarded to the encapsulated string.
11
13
  #
12
- # >> "lj".upcase
13
- # => "lj"
14
14
  # >> "lj".mb_chars.upcase.to_s
15
15
  # => "LJ"
16
16
  #
17
+ # NOTE: Ruby 2.4 and later support native Unicode case mappings:
18
+ #
19
+ # >> "lj".upcase
20
+ # => "LJ"
21
+ #
17
22
  # == Method chaining
18
23
  #
19
24
  # All the methods on the Chars proxy which normally return a string will return a Chars object. This allows
@@ -42,9 +47,9 @@ class String
42
47
  # iso_str.is_utf8? # => false
43
48
  def is_utf8?
44
49
  case encoding
45
- when Encoding::UTF_8
50
+ when Encoding::UTF_8, Encoding::US_ASCII
46
51
  valid_encoding?
47
- when Encoding::ASCII_8BIT, Encoding::US_ASCII
52
+ when Encoding::ASCII_8BIT
48
53
  dup.force_encoding(Encoding::UTF_8).valid_encoding?
49
54
  else
50
55
  false
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "erb"
2
- require "active_support/core_ext/kernel/singleton_class"
4
+ require "active_support/core_ext/module/redefine_method"
3
5
  require "active_support/multibyte/unicode"
4
6
 
5
7
  class ERB
@@ -9,25 +11,29 @@ class ERB
9
11
  HTML_ESCAPE_ONCE_REGEXP = /["><']|&(?!([a-zA-Z]+|(#\d+)|(#[xX][\dA-Fa-f]+));)/
10
12
  JSON_ESCAPE_REGEXP = /[\u2028\u2029&><]/u
11
13
 
14
+ # Following XML requirements: https://www.w3.org/TR/REC-xml/#NT-Name
15
+ TAG_NAME_START_REGEXP_SET = "@:A-Z_a-z\u{C0}-\u{D6}\u{D8}-\u{F6}\u{F8}-\u{2FF}\u{370}-\u{37D}\u{37F}-\u{1FFF}" \
16
+ "\u{200C}-\u{200D}\u{2070}-\u{218F}\u{2C00}-\u{2FEF}\u{3001}-\u{D7FF}\u{F900}-\u{FDCF}" \
17
+ "\u{FDF0}-\u{FFFD}\u{10000}-\u{EFFFF}"
18
+ TAG_NAME_START_REGEXP = /[^#{TAG_NAME_START_REGEXP_SET}]/
19
+ TAG_NAME_FOLLOWING_REGEXP = /[^#{TAG_NAME_START_REGEXP_SET}\-.0-9\u{B7}\u{0300}-\u{036F}\u{203F}-\u{2040}]/
20
+ TAG_NAME_REPLACEMENT_CHAR = "_"
21
+
12
22
  # A utility method for escaping HTML tag characters.
13
23
  # This method is also aliased as <tt>h</tt>.
14
24
  #
15
- # In your ERB templates, use this method to escape any unsafe content. For example:
16
- # <%= h @person.name %>
17
- #
18
25
  # puts html_escape('is a > 0 & a < 10?')
19
26
  # # => is a &gt; 0 &amp; a &lt; 10?
20
27
  def html_escape(s)
21
28
  unwrapped_html_escape(s).html_safe
22
29
  end
23
30
 
24
- # Aliasing twice issues a warning "discarding old...". Remove first to avoid it.
25
- remove_method(:h)
31
+ silence_redefinition_of_method :h
26
32
  alias h html_escape
27
33
 
28
34
  module_function :h
29
35
 
30
- singleton_class.send(:remove_method, :html_escape)
36
+ singleton_class.silence_redefinition_of_method :html_escape
31
37
  module_function :html_escape
32
38
 
33
39
  # HTML escapes strings but doesn't wrap them with an ActiveSupport::SafeBuffer.
@@ -86,7 +92,7 @@ class ERB
86
92
  # use inside HTML attributes.
87
93
  #
88
94
  # If your JSON is being used downstream for insertion into the DOM, be aware of
89
- # whether or not it is being inserted via +html()+. Most jQuery plugins do this.
95
+ # whether or not it is being inserted via <tt>html()</tt>. Most jQuery plugins do this.
90
96
  # If that is the case, be sure to +html_escape+ or +sanitize+ any user-generated
91
97
  # content returned by your JSON.
92
98
  #
@@ -117,6 +123,26 @@ class ERB
117
123
  end
118
124
 
119
125
  module_function :json_escape
126
+
127
+ # A utility method for escaping XML names of tags and names of attributes.
128
+ #
129
+ # xml_name_escape('1 < 2 & 3')
130
+ # # => "1___2___3"
131
+ #
132
+ # It follows the requirements of the specification: https://www.w3.org/TR/REC-xml/#NT-Name
133
+ def xml_name_escape(name)
134
+ name = name.to_s
135
+ return "" if name.blank?
136
+
137
+ starting_char = name[0].gsub(TAG_NAME_START_REGEXP, TAG_NAME_REPLACEMENT_CHAR)
138
+
139
+ return starting_char if name.size == 1
140
+
141
+ following_chars = name[1..-1].gsub(TAG_NAME_FOLLOWING_REGEXP, TAG_NAME_REPLACEMENT_CHAR)
142
+
143
+ starting_char + following_chars
144
+ end
145
+ module_function :xml_name_escape
120
146
  end
121
147
  end
122
148
 
@@ -135,10 +161,13 @@ end
135
161
  module ActiveSupport #:nodoc:
136
162
  class SafeBuffer < String
137
163
  UNSAFE_STRING_METHODS = %w(
138
- capitalize chomp chop delete downcase gsub lstrip next reverse rstrip
139
- slice squeeze strip sub succ swapcase tr tr_s upcase
164
+ capitalize chomp chop delete delete_prefix delete_suffix
165
+ downcase lstrip next reverse rstrip scrub slice squeeze strip
166
+ succ swapcase tr tr_s unicode_normalize upcase
140
167
  )
141
168
 
169
+ UNSAFE_STRING_METHODS_WITH_BACKREF = %w(gsub sub)
170
+
142
171
  alias_method :original_concat, :concat
143
172
  private :original_concat
144
173
 
@@ -150,15 +179,13 @@ module ActiveSupport #:nodoc:
150
179
  end
151
180
 
152
181
  def [](*args)
153
- if args.size < 2
154
- super
155
- elsif html_safe?
156
- new_safe_buffer = super
182
+ if html_safe?
183
+ new_string = super
157
184
 
158
- if new_safe_buffer
159
- new_safe_buffer.instance_variable_set :@html_safe, true
160
- end
185
+ return unless new_string
161
186
 
187
+ new_safe_buffer = new_string.is_a?(SafeBuffer) ? new_string : SafeBuffer.new(new_string)
188
+ new_safe_buffer.instance_variable_set :@html_safe, true
162
189
  new_safe_buffer
163
190
  else
164
191
  to_str[*args]
@@ -189,18 +216,41 @@ module ActiveSupport #:nodoc:
189
216
  end
190
217
  alias << concat
191
218
 
219
+ def insert(index, value)
220
+ super(index, html_escape_interpolated_argument(value))
221
+ end
222
+
192
223
  def prepend(value)
193
224
  super(html_escape_interpolated_argument(value))
194
225
  end
195
226
 
227
+ def replace(value)
228
+ super(html_escape_interpolated_argument(value))
229
+ end
230
+
231
+ def []=(*args)
232
+ if args.length == 3
233
+ super(args[0], args[1], html_escape_interpolated_argument(args[2]))
234
+ else
235
+ super(args[0], html_escape_interpolated_argument(args[1]))
236
+ end
237
+ end
238
+
196
239
  def +(other)
197
240
  dup.concat(other)
198
241
  end
199
242
 
243
+ def *(*)
244
+ new_string = super
245
+ new_safe_buffer = new_string.is_a?(SafeBuffer) ? new_string : SafeBuffer.new(new_string)
246
+ new_safe_buffer.instance_variable_set(:@html_safe, @html_safe)
247
+ new_safe_buffer
248
+ end
249
+
200
250
  def %(args)
201
251
  case args
202
252
  when Hash
203
- escaped_args = Hash[args.map { |k, arg| [k, html_escape_interpolated_argument(arg)] }]
253
+ escaped_args = args.transform_values { |arg| html_escape_interpolated_argument(arg) }
204
254
  else
205
255
  escaped_args = Array(args).map { |arg| html_escape_interpolated_argument(arg) }
206
256
  end
@@ -239,11 +289,45 @@ module ActiveSupport #:nodoc:
239
289
  end
240
290
  end
241
291
 
242
- private
292
+ UNSAFE_STRING_METHODS_WITH_BACKREF.each do |unsafe_method|
293
+ if unsafe_method.respond_to?(unsafe_method)
294
+ class_eval <<-EOT, __FILE__, __LINE__ + 1
295
+ def #{unsafe_method}(*args, &block) # def gsub(*args, &block)
296
+ if block # if block
297
+ to_str.#{unsafe_method}(*args) { |*params| # to_str.gsub(*args) { |*params|
298
+ set_block_back_references(block, $~) # set_block_back_references(block, $~)
299
+ block.call(*params) # block.call(*params)
300
+ } # }
301
+ else # else
302
+ to_str.#{unsafe_method}(*args) # to_str.gsub(*args)
303
+ end # end
304
+ end # end
305
+
306
+ def #{unsafe_method}!(*args, &block) # def gsub!(*args, &block)
307
+ @html_safe = false # @html_safe = false
308
+ if block # if block
309
+ super(*args) { |*params| # super(*args) { |*params|
310
+ set_block_back_references(block, $~) # set_block_back_references(block, $~)
311
+ block.call(*params) # block.call(*params)
312
+ } # }
313
+ else # else
314
+ super # super
315
+ end # end
316
+ end # end
317
+ EOT
318
+ end
319
+ end
243
320
 
321
+ private
244
322
  def html_escape_interpolated_argument(arg)
245
323
  (!html_safe? || arg.html_safe?) ? arg : CGI.escapeHTML(arg.to_s)
246
324
  end
325
+
326
+ def set_block_back_references(block, match_data)
327
+ block.binding.eval("proc { |m| $~ = m }").call(match_data)
328
+ rescue ArgumentError
329
+ # Can't create binding from C level Proc
330
+ end
247
331
  end
248
332
  end
249
333
 
@@ -251,7 +335,7 @@ class String
251
335
  # Marks a string as trusted safe. It will be inserted into HTML with no
252
336
  # additional escaping performed. It is your responsibility to ensure that the
253
337
  # string contains no malicious content. This method is equivalent to the
254
- # `raw` helper in views. It is recommended that you use `sanitize` instead of
338
+ # +raw+ helper in views. It is recommended that you use +sanitize+ instead of
255
339
  # this method. It should never be called on user input.
256
340
  def html_safe
257
341
  ActiveSupport::SafeBuffer.new(self)
@@ -1,4 +1,6 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class String
2
- alias_method :starts_with?, :start_with?
3
- alias_method :ends_with?, :end_with?
4
+ alias :starts_with? :start_with?
5
+ alias :ends_with? :end_with?
4
6
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class String
2
4
  # Strips indentation in heredocs.
3
5
  #
@@ -18,6 +20,8 @@ class String
18
20
  # Technically, it looks for the least indented non-empty line
19
21
  # in the whole string, and removes that amount of leading whitespace.
20
22
  def strip_heredoc
21
- gsub(/^#{scan(/^[ \t]*(?=\S)/).min}/, "".freeze)
23
+ gsub(/^#{scan(/^[ \t]*(?=\S)/).min}/, "").tap do |stripped|
24
+ stripped.freeze if frozen?
25
+ end
22
26
  end
23
27
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/core_ext/string/conversions"
2
4
  require "active_support/core_ext/time/zones"
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/core_ext/string/conversions"
2
4
  require "active_support/core_ext/string/filters"
3
5
  require "active_support/core_ext/string/multibyte"
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Symbol
4
+ def start_with?(*prefixes)
5
+ to_s.start_with?(*prefixes)
6
+ end unless method_defined?(:start_with?)
7
+
8
+ def end_with?(*suffixes)
9
+ to_s.end_with?(*suffixes)
10
+ end unless method_defined?(:end_with?)
11
+
12
+ alias :starts_with? :start_with?
13
+ alias :ends_with? :end_with?
14
+ end
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/symbol/starts_ends_with"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/core_ext/object/acts_like"
2
4
 
3
5
  class Time