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,29 +1,31 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class String
2
- # If you pass a single Fixnum, returns a substring of one character at that
4
+ # If you pass a single integer, returns a substring of one character at that
3
5
  # position. The first character of the string is at position 0, the next at
4
6
  # position 1, and so on. If a range is supplied, a substring containing
5
7
  # characters at offsets given by the range is returned. In both cases, if an
6
- # offset is negative, it is counted from the end of the string. Returns nil
8
+ # offset is negative, it is counted from the end of the string. Returns +nil+
7
9
  # if the initial offset falls outside the string. Returns an empty string if
8
10
  # the beginning of the range is greater than the end of the string.
9
11
  #
10
12
  # str = "hello"
11
- # str.at(0) #=> "h"
12
- # str.at(1..3) #=> "ell"
13
- # str.at(-2) #=> "l"
14
- # str.at(-2..-1) #=> "lo"
15
- # str.at(5) #=> nil
16
- # str.at(5..-1) #=> ""
13
+ # str.at(0) # => "h"
14
+ # str.at(1..3) # => "ell"
15
+ # str.at(-2) # => "l"
16
+ # str.at(-2..-1) # => "lo"
17
+ # str.at(5) # => nil
18
+ # str.at(5..-1) # => ""
17
19
  #
18
20
  # If a Regexp is given, the matching portion of the string is returned.
19
21
  # If a String is given, that given string is returned if it occurs in
20
- # the string. In both cases, nil is returned if there is no match.
22
+ # the string. In both cases, +nil+ is returned if there is no match.
21
23
  #
22
24
  # str = "hello"
23
- # str.at(/lo/) #=> "lo"
24
- # str.at(/ol/) #=> nil
25
- # str.at("lo") #=> "lo"
26
- # str.at("ol") #=> nil
25
+ # str.at(/lo/) # => "lo"
26
+ # str.at(/ol/) # => nil
27
+ # str.at("lo") # => "lo"
28
+ # str.at("ol") # => nil
27
29
  def at(position)
28
30
  self[position]
29
31
  end
@@ -32,73 +34,62 @@ class String
32
34
  # If the position is negative, it is counted from the end of the string.
33
35
  #
34
36
  # str = "hello"
35
- # str.from(0) #=> "hello"
36
- # str.from(3) #=> "lo"
37
- # str.from(-2) #=> "lo"
37
+ # str.from(0) # => "hello"
38
+ # str.from(3) # => "lo"
39
+ # str.from(-2) # => "lo"
38
40
  #
39
41
  # You can mix it with +to+ method and do fun things like:
40
42
  #
41
43
  # str = "hello"
42
- # str.from(0).to(-1) #=> "hello"
43
- # str.from(1).to(-2) #=> "ell"
44
+ # str.from(0).to(-1) # => "hello"
45
+ # str.from(1).to(-2) # => "ell"
44
46
  def from(position)
45
- self[position..-1]
47
+ self[position, length]
46
48
  end
47
49
 
48
50
  # Returns a substring from the beginning of the string to the given position.
49
51
  # If the position is negative, it is counted from the end of the string.
50
52
  #
51
53
  # str = "hello"
52
- # str.to(0) #=> "h"
53
- # str.to(3) #=> "hell"
54
- # str.to(-2) #=> "hell"
54
+ # str.to(0) # => "h"
55
+ # str.to(3) # => "hell"
56
+ # str.to(-2) # => "hell"
55
57
  #
56
58
  # You can mix it with +from+ method and do fun things like:
57
59
  #
58
60
  # str = "hello"
59
- # str.from(0).to(-1) #=> "hello"
60
- # str.from(1).to(-2) #=> "ell"
61
+ # str.from(0).to(-1) # => "hello"
62
+ # str.from(1).to(-2) # => "ell"
61
63
  def to(position)
62
- self[0..position]
64
+ position += size if position < 0
65
+ self[0, position + 1] || +""
63
66
  end
64
67
 
65
68
  # Returns the first character. If a limit is supplied, returns a substring
66
69
  # from the beginning of the string until it reaches the limit value. If the
67
- # given limit is greater than or equal to the string length, returns self.
70
+ # given limit is greater than or equal to the string length, returns a copy of self.
68
71
  #
69
72
  # str = "hello"
70
- # str.first #=> "h"
71
- # str.first(1) #=> "h"
72
- # str.first(2) #=> "he"
73
- # str.first(0) #=> ""
74
- # str.first(6) #=> "hello"
73
+ # str.first # => "h"
74
+ # str.first(1) # => "h"
75
+ # str.first(2) # => "he"
76
+ # str.first(0) # => ""
77
+ # str.first(6) # => "hello"
75
78
  def first(limit = 1)
76
- if limit == 0
77
- ''
78
- elsif limit >= size
79
- self
80
- else
81
- to(limit - 1)
82
- end
79
+ self[0, limit] || raise(ArgumentError, "negative limit")
83
80
  end
84
81
 
85
82
  # Returns the last character of the string. If a limit is supplied, returns a substring
86
83
  # from the end of the string until it reaches the limit value (counting backwards). If
87
- # the given limit is greater than or equal to the string length, returns self.
84
+ # the given limit is greater than or equal to the string length, returns a copy of self.
88
85
  #
89
86
  # str = "hello"
90
- # str.last #=> "o"
91
- # str.last(1) #=> "o"
92
- # str.last(2) #=> "lo"
93
- # str.last(0) #=> ""
94
- # str.last(6) #=> "hello"
87
+ # str.last # => "o"
88
+ # str.last(1) # => "o"
89
+ # str.last(2) # => "lo"
90
+ # str.last(0) # => ""
91
+ # str.last(6) # => "hello"
95
92
  def last(limit = 1)
96
- if limit == 0
97
- ''
98
- elsif limit >= size
99
- self
100
- else
101
- from(-limit)
102
- end
93
+ self[[length - limit, 0].max, limit] || raise(ArgumentError, "negative limit")
103
94
  end
104
95
  end
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class String
2
- # Enable more predictable duck-typing on String-like classes. See <tt>Object#acts_like?</tt>.
4
+ # Enables more predictable duck-typing on String-like classes. See <tt>Object#acts_like?</tt>.
3
5
  def acts_like_string?
4
6
  true
5
7
  end
@@ -1,5 +1,7 @@
1
- require 'date'
2
- require 'active_support/core_ext/time/calculations'
1
+ # frozen_string_literal: true
2
+
3
+ require "date"
4
+ require "active_support/core_ext/time/calculations"
3
5
 
4
6
  class String
5
7
  # Converts a string to a Time value.
@@ -14,10 +16,13 @@ class String
14
16
  # "06:12".to_time # => 2012-12-13 06:12:00 +0100
15
17
  # "2012-12-13 06:12".to_time # => 2012-12-13 06:12:00 +0100
16
18
  # "2012-12-13T06:12".to_time # => 2012-12-13 06:12:00 +0100
17
- # "2012-12-13T06:12".to_time(:utc) # => 2012-12-13 05:12:00 UTC
19
+ # "2012-12-13T06:12".to_time(:utc) # => 2012-12-13 06:12:00 UTC
20
+ # "12/13/2012".to_time # => ArgumentError: argument out of range
21
+ # "1604326192".to_time # => ArgumentError: argument out of range
18
22
  def to_time(form = :local)
19
23
  parts = Date._parse(self, false)
20
- return if parts.empty?
24
+ used_keys = %i(year mon mday hour min sec sec_fraction offset)
25
+ return if (parts.keys & used_keys).empty?
21
26
 
22
27
  now = Time.now
23
28
  time = Time.new(
@@ -30,25 +35,25 @@ class String
30
35
  parts.fetch(:offset, form == :utc ? 0 : nil)
31
36
  )
32
37
 
33
- form == :utc ? time.utc : time.getlocal
38
+ form == :utc ? time.utc : time.to_time
34
39
  end
35
40
 
36
41
  # Converts a string to a Date value.
37
42
  #
38
- # "1-1-2012".to_date #=> Sun, 01 Jan 2012
39
- # "01/01/2012".to_date #=> Sun, 01 Jan 2012
40
- # "2012-12-13".to_date #=> Thu, 13 Dec 2012
41
- # "12/13/2012".to_date #=> ArgumentError: invalid date
43
+ # "1-1-2012".to_date # => Sun, 01 Jan 2012
44
+ # "01/01/2012".to_date # => Sun, 01 Jan 2012
45
+ # "2012-12-13".to_date # => Thu, 13 Dec 2012
46
+ # "12/13/2012".to_date # => ArgumentError: invalid date
42
47
  def to_date
43
48
  ::Date.parse(self, false) unless blank?
44
49
  end
45
50
 
46
51
  # Converts a string to a DateTime value.
47
52
  #
48
- # "1-1-2012".to_datetime #=> Sun, 01 Jan 2012 00:00:00 +0000
49
- # "01/01/2012 23:59:59".to_datetime #=> Sun, 01 Jan 2012 23:59:59 +0000
50
- # "2012-12-13 12:50".to_datetime #=> Thu, 13 Dec 2012 12:50:00 +0000
51
- # "12/13/2012".to_datetime #=> ArgumentError: invalid date
53
+ # "1-1-2012".to_datetime # => Sun, 01 Jan 2012 00:00:00 +0000
54
+ # "01/01/2012 23:59:59".to_datetime # => Sun, 01 Jan 2012 23:59:59 +0000
55
+ # "2012-12-13 12:50".to_datetime # => Thu, 13 Dec 2012 12:50:00 +0000
56
+ # "12/13/2012".to_datetime # => ArgumentError: invalid date
52
57
  def to_datetime
53
58
  ::DateTime.parse(self, false) unless blank?
54
59
  end
@@ -1,10 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class String
2
4
  # The inverse of <tt>String#include?</tt>. Returns true if the string
3
5
  # does not include the other string.
4
6
  #
5
- # "hello".exclude? "lo" #=> false
6
- # "hello".exclude? "ol" #=> true
7
- # "hello".exclude? ?h #=> false
7
+ # "hello".exclude? "lo" # => false
8
+ # "hello".exclude? "ol" # => true
9
+ # "hello".exclude? ?h # => false
8
10
  def exclude?(string)
9
11
  !include?(string)
10
12
  end
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class String
2
4
  # Returns the string, first removing all whitespace on both ends of
3
5
  # the string, and then changing remaining consecutive whitespace
4
6
  # groups into one space each.
5
7
  #
6
- # Note that it handles both ASCII and Unicode whitespace like mongolian vowel separator (U+180E).
8
+ # Note that it handles both ASCII and Unicode whitespace.
7
9
  #
8
10
  # %{ Multi-line
9
11
  # string }.squish # => "Multi-line string"
@@ -13,10 +15,33 @@ class String
13
15
  end
14
16
 
15
17
  # Performs a destructive squish. See String#squish.
18
+ # str = " foo bar \n \t boo"
19
+ # str.squish! # => "foo bar boo"
20
+ # str # => "foo bar boo"
16
21
  def squish!
17
- gsub!(/\A[[:space:]]+/, '')
18
- gsub!(/[[:space:]]+\z/, '')
19
- gsub!(/[[:space:]]+/, ' ')
22
+ gsub!(/[[:space:]]+/, " ")
23
+ strip!
24
+ self
25
+ end
26
+
27
+ # Returns a new string with all occurrences of the patterns removed.
28
+ # str = "foo bar test"
29
+ # str.remove(" test") # => "foo bar"
30
+ # str.remove(" test", /bar/) # => "foo "
31
+ # str # => "foo bar test"
32
+ def remove(*patterns)
33
+ dup.remove!(*patterns)
34
+ end
35
+
36
+ # Alters the string by removing all occurrences of the patterns.
37
+ # str = "foo bar test"
38
+ # str.remove!(" test", /bar/) # => "foo "
39
+ # str # => "foo "
40
+ def remove!(*patterns)
41
+ patterns.each do |pattern|
42
+ gsub! pattern, ""
43
+ end
44
+
20
45
  self
21
46
  end
22
47
 
@@ -41,8 +66,8 @@ class String
41
66
  def truncate(truncate_at, options = {})
42
67
  return dup unless length > truncate_at
43
68
 
44
- options[:omission] ||= '...'
45
- length_with_room_for_omission = truncate_at - options[:omission].length
69
+ omission = options[:omission] || "..."
70
+ length_with_room_for_omission = truncate_at - omission.length
46
71
  stop = \
47
72
  if options[:separator]
48
73
  rindex(options[:separator], length_with_room_for_omission) || length_with_room_for_omission
@@ -50,6 +75,71 @@ class String
50
75
  length_with_room_for_omission
51
76
  end
52
77
 
53
- "#{self[0...stop]}#{options[:omission]}"
78
+ +"#{self[0, stop]}#{omission}"
79
+ end
80
+
81
+ # Truncates +text+ to at most <tt>bytesize</tt> bytes in length without
82
+ # breaking string encoding by splitting multibyte characters or breaking
83
+ # grapheme clusters ("perceptual characters") by truncating at combining
84
+ # characters.
85
+ #
86
+ # >> "🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪".size
87
+ # => 20
88
+ # >> "🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪".bytesize
89
+ # => 80
90
+ # >> "🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪".truncate_bytes(20)
91
+ # => "🔪🔪🔪🔪…"
92
+ #
93
+ # The truncated text ends with the <tt>:omission</tt> string, defaulting
94
+ # to "…", for a total length not exceeding <tt>bytesize</tt>.
95
+ def truncate_bytes(truncate_at, omission: "…")
96
+ omission ||= ""
97
+
98
+ case
99
+ when bytesize <= truncate_at
100
+ dup
101
+ when omission.bytesize > truncate_at
102
+ raise ArgumentError, "Omission #{omission.inspect} is #{omission.bytesize}, larger than the truncation length of #{truncate_at} bytes"
103
+ when omission.bytesize == truncate_at
104
+ omission.dup
105
+ else
106
+ self.class.new.tap do |cut|
107
+ cut_at = truncate_at - omission.bytesize
108
+
109
+ each_grapheme_cluster do |grapheme|
110
+ if cut.bytesize + grapheme.bytesize <= cut_at
111
+ cut << grapheme
112
+ else
113
+ break
114
+ end
115
+ end
116
+
117
+ cut << omission
118
+ end
119
+ end
120
+ end
121
+
122
+ # Truncates a given +text+ after a given number of words (<tt>words_count</tt>):
123
+ #
124
+ # 'Once upon a time in a world far far away'.truncate_words(4)
125
+ # # => "Once upon a time..."
126
+ #
127
+ # Pass a string or regexp <tt>:separator</tt> to specify a different separator of words:
128
+ #
129
+ # 'Once<br>upon<br>a<br>time<br>in<br>a<br>world'.truncate_words(5, separator: '<br>')
130
+ # # => "Once<br>upon<br>a<br>time<br>in..."
131
+ #
132
+ # The last characters will be replaced with the <tt>:omission</tt> string (defaults to "..."):
133
+ #
134
+ # 'And they found that many people were sleeping better.'.truncate_words(5, omission: '... (continued)')
135
+ # # => "And they found that many... (continued)"
136
+ def truncate_words(words_count, options = {})
137
+ sep = options[:separator] || /\s+/
138
+ sep = Regexp.escape(sep.to_s) unless Regexp === sep
139
+ if self =~ /\A((?>.+?#{sep}){#{words_count - 1}}.+?)#{sep}.*/m
140
+ $1 + (options[:omission] || "...")
141
+ else
142
+ dup
143
+ end
54
144
  end
55
145
  end
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class String
2
4
  # Same as +indent+, except it indents the receiver in-place.
3
5
  #
4
6
  # Returns the indented string, or +nil+ if there was nothing to indent.
5
- def indent!(amount, indent_string=nil, indent_empty_lines=false)
6
- indent_string = indent_string || self[/^[ \t]/] || ' '
7
+ def indent!(amount, indent_string = nil, indent_empty_lines = false)
8
+ indent_string = indent_string || self[/^[ \t]/] || " "
7
9
  re = indent_empty_lines ? /^/ : /^(?!$)/
8
10
  gsub!(re, indent_string * amount)
9
11
  end
@@ -37,7 +39,7 @@ class String
37
39
  # "foo\n\nbar".indent(2) # => " foo\n\n bar"
38
40
  # "foo\n\nbar".indent(2, nil, true) # => " foo\n \n bar"
39
41
  #
40
- def indent(amount, indent_string=nil, indent_empty_lines=false)
41
- dup.tap {|_| _.indent!(amount, indent_string, indent_empty_lines)}
42
+ def indent(amount, indent_string = nil, indent_empty_lines = false)
43
+ dup.tap { |_| _.indent!(amount, indent_string, indent_empty_lines) }
42
44
  end
43
45
  end
@@ -1,5 +1,7 @@
1
- require 'active_support/inflector/methods'
2
- require 'active_support/inflector/transliterate'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/inflector/methods"
4
+ require "active_support/inflector/transliterate"
3
5
 
4
6
  # String inflections define new methods on the String class to transform names for different purposes.
5
7
  # For instance, you can figure out the name of a table from the name of a class.
@@ -28,10 +30,12 @@ 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
34
- self
38
+ dup
35
39
  else
36
40
  ActiveSupport::Inflector.pluralize(self, locale)
37
41
  end
@@ -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
- # in the string. It returns nil when the name is not in CamelCase
71
- # or is not initialized. See ActiveSupport::Inflector.safe_constantize
78
+ # in the string. It returns +nil+ when the name is not in CamelCase
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,14 +147,20 @@ 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
128
155
 
129
156
  # Removes the module part from the constant expression in the string.
130
157
  #
131
- # 'ActiveRecord::CoreExtensions::String::Inflections'.demodulize # => "Inflections"
132
- # 'Inflections'.demodulize # => "Inflections"
158
+ # 'ActiveSupport::Inflector::Inflections'.demodulize # => "Inflections"
159
+ # 'Inflections'.demodulize # => "Inflections"
160
+ # '::Inflections'.demodulize # => "Inflections"
161
+ # ''.demodulize # => ''
162
+ #
163
+ # See ActiveSupport::Inflector.demodulize.
133
164
  #
134
165
  # See also +deconstantize+.
135
166
  def demodulize
@@ -144,6 +175,8 @@ class String
144
175
  # '::String'.deconstantize # => ""
145
176
  # ''.deconstantize # => ""
146
177
  #
178
+ # See ActiveSupport::Inflector.deconstantize.
179
+ #
147
180
  # See also +demodulize+.
148
181
  def deconstantize
149
182
  ActiveSupport::Inflector.deconstantize(self)
@@ -151,6 +184,11 @@ class String
151
184
 
152
185
  # Replaces special characters in a string so that it may be used as part of a 'pretty' URL.
153
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
+ #
154
192
  # class Person
155
193
  # def to_param
156
194
  # "#{id}-#{name.parameterize}"
@@ -162,41 +200,82 @@ class String
162
200
  #
163
201
  # <%= link_to(@person.name, person_path) %>
164
202
  # # => <a href="/person/1-donald-e-knuth">Donald E. Knuth</a>
165
- def parameterize(sep = '-')
166
- ActiveSupport::Inflector.parameterize(self, sep)
203
+ #
204
+ # To preserve the case of the characters in a string, use the +preserve_case+ argument.
205
+ #
206
+ # class Person
207
+ # def to_param
208
+ # "#{id}-#{name.parameterize(preserve_case: true)}"
209
+ # end
210
+ # end
211
+ #
212
+ # @person = Person.find(1)
213
+ # # => #<Person id: 1, name: "Donald E. Knuth">
214
+ #
215
+ # <%= link_to(@person.name, person_path) %>
216
+ # # => <a href="/person/1-Donald-E-Knuth">Donald E. Knuth</a>
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)
167
221
  end
168
222
 
169
223
  # Creates the name of a table like Rails does for models to table names. This method
170
224
  # uses the +pluralize+ method on the last word in the string.
171
225
  #
172
226
  # 'RawScaledScorer'.tableize # => "raw_scaled_scorers"
173
- # 'egg_and_ham'.tableize # => "egg_and_hams"
227
+ # 'ham_and_egg'.tableize # => "ham_and_eggs"
174
228
  # 'fancyCategory'.tableize # => "fancy_categories"
229
+ #
230
+ # See ActiveSupport::Inflector.tableize.
175
231
  def tableize
176
232
  ActiveSupport::Inflector.tableize(self)
177
233
  end
178
234
 
179
- # Create a class name from a plural table name like Rails does for table names to models.
235
+ # Creates a class name from a plural table name like Rails does for table names to models.
180
236
  # Note that this returns a string and not a class. (To convert to an actual class
181
237
  # follow +classify+ with +constantize+.)
182
238
  #
183
- # 'egg_and_hams'.classify # => "EggAndHam"
239
+ # 'ham_and_eggs'.classify # => "HamAndEgg"
184
240
  # 'posts'.classify # => "Post"
185
241
  #
186
- # Singular names are not handled correctly.
187
- #
188
- # 'business'.classify # => "Busines"
242
+ # See ActiveSupport::Inflector.classify.
189
243
  def classify
190
244
  ActiveSupport::Inflector.classify(self)
191
245
  end
192
246
 
193
- # Capitalizes the first word, turns underscores into spaces, and strips '_id'.
247
+ # Capitalizes the first word, turns underscores into spaces, and (by default)strips a
248
+ # trailing '_id' if present.
194
249
  # Like +titleize+, this is meant for creating pretty output.
195
250
  #
196
- # 'employee_salary'.humanize # => "Employee salary"
197
- # 'author_id'.humanize # => "Author"
198
- def humanize
199
- ActiveSupport::Inflector.humanize(self)
251
+ # The capitalization of the first word can be turned off by setting the
252
+ # optional parameter +capitalize+ to false.
253
+ # By default, this parameter is true.
254
+ #
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)
268
+ end
269
+
270
+ # Converts just the first character to uppercase.
271
+ #
272
+ # 'what a Lovely Day'.upcase_first # => "What a Lovely Day"
273
+ # 'w'.upcase_first # => "W"
274
+ # ''.upcase_first # => ""
275
+ #
276
+ # See ActiveSupport::Inflector.upcase_first.
277
+ def upcase_first
278
+ ActiveSupport::Inflector.upcase_first(self)
200
279
  end
201
280
 
202
281
  # Creates a foreign key name from a class name.
@@ -206,6 +285,8 @@ class String
206
285
  # 'Message'.foreign_key # => "message_id"
207
286
  # 'Message'.foreign_key(false) # => "messageid"
208
287
  # 'Admin::Post'.foreign_key # => "post_id"
288
+ #
289
+ # See ActiveSupport::Inflector.foreign_key.
209
290
  def foreign_key(separate_class_name_and_id_with_underscore = true)
210
291
  ActiveSupport::Inflector.foreign_key(self, separate_class_name_and_id_with_underscore)
211
292
  end
@@ -1,4 +1,7 @@
1
- require 'active_support/string_inquirer'
1
+ # frozen_string_literal: true
2
+
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,