activesupport 1.2.4 → 8.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (309) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +505 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.rdoc +40 -0
  5. data/lib/active_support/actionable_error.rb +50 -0
  6. data/lib/active_support/all.rb +5 -0
  7. data/lib/active_support/array_inquirer.rb +50 -0
  8. data/lib/active_support/backtrace_cleaner.rb +234 -0
  9. data/lib/active_support/benchmark.rb +21 -0
  10. data/lib/active_support/benchmarkable.rb +53 -0
  11. data/lib/active_support/broadcast_logger.rb +238 -0
  12. data/lib/active_support/builder.rb +8 -0
  13. data/lib/active_support/cache/coder.rb +153 -0
  14. data/lib/active_support/cache/entry.rb +134 -0
  15. data/lib/active_support/cache/file_store.rb +244 -0
  16. data/lib/active_support/cache/mem_cache_store.rb +288 -0
  17. data/lib/active_support/cache/memory_store.rb +264 -0
  18. data/lib/active_support/cache/null_store.rb +62 -0
  19. data/lib/active_support/cache/redis_cache_store.rb +498 -0
  20. data/lib/active_support/cache/serializer_with_fallback.rb +152 -0
  21. data/lib/active_support/cache/strategy/local_cache.rb +246 -0
  22. data/lib/active_support/cache/strategy/local_cache_middleware.rb +45 -0
  23. data/lib/active_support/cache.rb +1170 -0
  24. data/lib/active_support/callbacks.rb +960 -0
  25. data/lib/active_support/class_attribute.rb +33 -0
  26. data/lib/active_support/code_generator.rb +79 -0
  27. data/lib/active_support/concern.rb +217 -0
  28. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +18 -0
  29. data/lib/active_support/concurrency/null_lock.rb +13 -0
  30. data/lib/active_support/concurrency/share_lock.rb +225 -0
  31. data/lib/active_support/concurrency/thread_monitor.rb +55 -0
  32. data/lib/active_support/configurable.rb +193 -0
  33. data/lib/active_support/configuration_file.rb +60 -0
  34. data/lib/active_support/continuous_integration.rb +145 -0
  35. data/lib/active_support/core_ext/array/access.rb +100 -0
  36. data/lib/active_support/core_ext/array/conversions.rb +209 -26
  37. data/lib/active_support/core_ext/array/extract.rb +21 -0
  38. data/lib/active_support/core_ext/array/extract_options.rb +31 -0
  39. data/lib/active_support/core_ext/array/grouping.rb +109 -0
  40. data/lib/active_support/core_ext/array/inquiry.rb +19 -0
  41. data/lib/active_support/core_ext/array/wrap.rb +48 -0
  42. data/lib/active_support/core_ext/array.rb +8 -4
  43. data/lib/active_support/core_ext/benchmark.rb +6 -0
  44. data/lib/active_support/core_ext/big_decimal/conversions.rb +14 -0
  45. data/lib/active_support/core_ext/big_decimal.rb +3 -0
  46. data/lib/active_support/core_ext/class/attribute.rb +137 -0
  47. data/lib/active_support/core_ext/class/attribute_accessors.rb +6 -0
  48. data/lib/active_support/core_ext/class/subclasses.rb +24 -0
  49. data/lib/active_support/core_ext/class.rb +4 -0
  50. data/lib/active_support/core_ext/date/acts_like.rb +10 -0
  51. data/lib/active_support/core_ext/date/blank.rb +18 -0
  52. data/lib/active_support/core_ext/date/calculations.rb +161 -0
  53. data/lib/active_support/core_ext/date/conversions.rb +95 -28
  54. data/lib/active_support/core_ext/date/zones.rb +8 -0
  55. data/lib/active_support/core_ext/date.rb +6 -5
  56. data/lib/active_support/core_ext/date_and_time/calculations.rb +374 -0
  57. data/lib/active_support/core_ext/date_and_time/compatibility.rb +23 -0
  58. data/lib/active_support/core_ext/date_and_time/zones.rb +40 -0
  59. data/lib/active_support/core_ext/date_time/acts_like.rb +16 -0
  60. data/lib/active_support/core_ext/date_time/blank.rb +18 -0
  61. data/lib/active_support/core_ext/date_time/calculations.rb +215 -0
  62. data/lib/active_support/core_ext/date_time/compatibility.rb +16 -0
  63. data/lib/active_support/core_ext/date_time/conversions.rb +108 -0
  64. data/lib/active_support/core_ext/date_time.rb +7 -0
  65. data/lib/active_support/core_ext/digest/uuid.rb +76 -0
  66. data/lib/active_support/core_ext/digest.rb +3 -0
  67. data/lib/active_support/core_ext/enumerable.rb +277 -7
  68. data/lib/active_support/core_ext/erb/util.rb +201 -0
  69. data/lib/active_support/core_ext/file/atomic.rb +72 -0
  70. data/lib/active_support/core_ext/file.rb +3 -0
  71. data/lib/active_support/core_ext/hash/conversions.rb +262 -0
  72. data/lib/active_support/core_ext/hash/deep_merge.rb +43 -0
  73. data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
  74. data/lib/active_support/core_ext/hash/except.rb +12 -0
  75. data/lib/active_support/core_ext/hash/indifferent_access.rb +19 -55
  76. data/lib/active_support/core_ext/hash/keys.rb +134 -44
  77. data/lib/active_support/core_ext/hash/reverse_merge.rb +22 -22
  78. data/lib/active_support/core_ext/hash/slice.rb +27 -0
  79. data/lib/active_support/core_ext/hash.rb +9 -8
  80. data/lib/active_support/core_ext/integer/inflections.rb +29 -13
  81. data/lib/active_support/core_ext/integer/multiple.rb +12 -0
  82. data/lib/active_support/core_ext/integer/time.rb +22 -0
  83. data/lib/active_support/core_ext/integer.rb +4 -6
  84. data/lib/active_support/core_ext/kernel/concern.rb +14 -0
  85. data/lib/active_support/core_ext/kernel/reporting.rb +45 -0
  86. data/lib/active_support/core_ext/kernel/singleton_class.rb +8 -0
  87. data/lib/active_support/core_ext/kernel.rb +4 -78
  88. data/lib/active_support/core_ext/load_error.rb +6 -35
  89. data/lib/active_support/core_ext/module/aliasing.rb +31 -0
  90. data/lib/active_support/core_ext/module/anonymous.rb +30 -0
  91. data/lib/active_support/core_ext/module/attr_internal.rb +48 -0
  92. data/lib/active_support/core_ext/module/attribute_accessors.rb +214 -0
  93. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +175 -0
  94. data/lib/active_support/core_ext/module/concerning.rb +140 -0
  95. data/lib/active_support/core_ext/module/delegation.rb +225 -0
  96. data/lib/active_support/core_ext/module/deprecation.rb +25 -0
  97. data/lib/active_support/core_ext/module/introspection.rb +65 -0
  98. data/lib/active_support/core_ext/module/redefine_method.rb +40 -0
  99. data/lib/active_support/core_ext/module/remove_method.rb +17 -0
  100. data/lib/active_support/core_ext/module.rb +13 -0
  101. data/lib/active_support/core_ext/name_error.rb +59 -0
  102. data/lib/active_support/core_ext/numeric/bytes.rb +73 -42
  103. data/lib/active_support/core_ext/numeric/conversions.rb +145 -0
  104. data/lib/active_support/core_ext/numeric/time.rb +64 -57
  105. data/lib/active_support/core_ext/numeric.rb +4 -6
  106. data/lib/active_support/core_ext/object/acts_like.rb +45 -0
  107. data/lib/active_support/core_ext/object/blank.rb +199 -0
  108. data/lib/active_support/core_ext/object/conversions.rb +6 -0
  109. data/lib/active_support/core_ext/object/deep_dup.rb +71 -0
  110. data/lib/active_support/core_ext/object/duplicable.rb +69 -0
  111. data/lib/active_support/core_ext/object/inclusion.rb +37 -0
  112. data/lib/active_support/core_ext/object/instance_variables.rb +32 -0
  113. data/lib/active_support/core_ext/object/json.rb +267 -0
  114. data/lib/active_support/core_ext/object/to_param.rb +3 -0
  115. data/lib/active_support/core_ext/object/to_query.rb +93 -0
  116. data/lib/active_support/core_ext/object/try.rb +158 -0
  117. data/lib/active_support/core_ext/object/with.rb +46 -0
  118. data/lib/active_support/core_ext/object/with_options.rb +101 -0
  119. data/lib/active_support/core_ext/object.rb +17 -0
  120. data/lib/active_support/core_ext/pathname/blank.rb +20 -0
  121. data/lib/active_support/core_ext/pathname/existence.rb +23 -0
  122. data/lib/active_support/core_ext/pathname.rb +4 -0
  123. data/lib/active_support/core_ext/range/compare_range.rb +57 -0
  124. data/lib/active_support/core_ext/range/conversions.rb +58 -17
  125. data/lib/active_support/core_ext/range/overlap.rb +40 -0
  126. data/lib/active_support/core_ext/range/sole.rb +17 -0
  127. data/lib/active_support/core_ext/range.rb +5 -4
  128. data/lib/active_support/core_ext/regexp.rb +14 -0
  129. data/lib/active_support/core_ext/securerandom.rb +57 -0
  130. data/lib/active_support/core_ext/string/access.rb +93 -56
  131. data/lib/active_support/core_ext/string/behavior.rb +8 -0
  132. data/lib/active_support/core_ext/string/conversions.rb +57 -16
  133. data/lib/active_support/core_ext/string/exclude.rb +13 -0
  134. data/lib/active_support/core_ext/string/filters.rb +151 -0
  135. data/lib/active_support/core_ext/string/indent.rb +45 -0
  136. data/lib/active_support/core_ext/string/inflections.rb +297 -54
  137. data/lib/active_support/core_ext/string/inquiry.rb +16 -0
  138. data/lib/active_support/core_ext/string/multibyte.rb +67 -0
  139. data/lib/active_support/core_ext/string/output_safety.rb +235 -0
  140. data/lib/active_support/core_ext/string/starts_ends_with.rb +4 -18
  141. data/lib/active_support/core_ext/string/strip.rb +27 -0
  142. data/lib/active_support/core_ext/string/zones.rb +16 -0
  143. data/lib/active_support/core_ext/string.rb +14 -10
  144. data/lib/active_support/core_ext/symbol/starts_ends_with.rb +6 -0
  145. data/lib/active_support/core_ext/symbol.rb +3 -0
  146. data/lib/active_support/core_ext/thread/backtrace/location.rb +7 -0
  147. data/lib/active_support/core_ext/time/acts_like.rb +10 -0
  148. data/lib/active_support/core_ext/time/calculations.rb +358 -153
  149. data/lib/active_support/core_ext/time/compatibility.rb +15 -0
  150. data/lib/active_support/core_ext/time/conversions.rb +69 -30
  151. data/lib/active_support/core_ext/time/zones.rb +97 -0
  152. data/lib/active_support/core_ext/time.rb +6 -6
  153. data/lib/active_support/core_ext.rb +5 -1
  154. data/lib/active_support/current_attributes/test_helper.rb +13 -0
  155. data/lib/active_support/current_attributes.rb +243 -0
  156. data/lib/active_support/deep_mergeable.rb +53 -0
  157. data/lib/active_support/delegation.rb +183 -0
  158. data/lib/active_support/dependencies/autoload.rb +72 -0
  159. data/lib/active_support/dependencies/interlock.rb +55 -0
  160. data/lib/active_support/dependencies/require_dependency.rb +28 -0
  161. data/lib/active_support/dependencies.rb +84 -222
  162. data/lib/active_support/deprecation/behaviors.rb +148 -0
  163. data/lib/active_support/deprecation/constant_accessor.rb +74 -0
  164. data/lib/active_support/deprecation/deprecators.rb +104 -0
  165. data/lib/active_support/deprecation/disallowed.rb +54 -0
  166. data/lib/active_support/deprecation/method_wrappers.rb +68 -0
  167. data/lib/active_support/deprecation/proxy_wrappers.rb +189 -0
  168. data/lib/active_support/deprecation/reporting.rb +162 -0
  169. data/lib/active_support/deprecation.rb +81 -0
  170. data/lib/active_support/deprecator.rb +7 -0
  171. data/lib/active_support/descendants_tracker.rb +112 -0
  172. data/lib/active_support/digest.rb +22 -0
  173. data/lib/active_support/duration/iso8601_parser.rb +123 -0
  174. data/lib/active_support/duration/iso8601_serializer.rb +64 -0
  175. data/lib/active_support/duration.rb +524 -0
  176. data/lib/active_support/editor.rb +70 -0
  177. data/lib/active_support/encrypted_configuration.rb +126 -0
  178. data/lib/active_support/encrypted_file.rb +133 -0
  179. data/lib/active_support/environment_inquirer.rb +40 -0
  180. data/lib/active_support/error_reporter/test_helper.rb +15 -0
  181. data/lib/active_support/error_reporter.rb +318 -0
  182. data/lib/active_support/event_reporter/test_helper.rb +32 -0
  183. data/lib/active_support/event_reporter.rb +592 -0
  184. data/lib/active_support/evented_file_update_checker.rb +185 -0
  185. data/lib/active_support/execution_context/test_helper.rb +13 -0
  186. data/lib/active_support/execution_context.rb +110 -0
  187. data/lib/active_support/execution_wrapper.rb +150 -0
  188. data/lib/active_support/executor/test_helper.rb +7 -0
  189. data/lib/active_support/executor.rb +8 -0
  190. data/lib/active_support/file_update_checker.rb +166 -0
  191. data/lib/active_support/fork_tracker.rb +43 -0
  192. data/lib/active_support/gem_version.rb +17 -0
  193. data/lib/active_support/gzip.rb +41 -0
  194. data/lib/active_support/hash_with_indifferent_access.rb +464 -0
  195. data/lib/active_support/html_safe_translation.rb +56 -0
  196. data/lib/active_support/i18n.rb +17 -0
  197. data/lib/active_support/i18n_railtie.rb +140 -0
  198. data/lib/active_support/inflections.rb +68 -49
  199. data/lib/active_support/inflector/inflections.rb +290 -0
  200. data/lib/active_support/inflector/methods.rb +387 -0
  201. data/lib/active_support/inflector/transliterate.rb +147 -0
  202. data/lib/active_support/inflector.rb +7 -164
  203. data/lib/active_support/isolated_execution_state.rb +76 -0
  204. data/lib/active_support/json/decoding.rb +78 -0
  205. data/lib/active_support/json/encoding.rb +256 -0
  206. data/lib/active_support/json.rb +4 -0
  207. data/lib/active_support/key_generator.rb +66 -0
  208. data/lib/active_support/lazy_load_hooks.rb +107 -0
  209. data/lib/active_support/locale/en.rb +33 -0
  210. data/lib/active_support/locale/en.yml +141 -0
  211. data/lib/active_support/log_subscriber/test_helper.rb +106 -0
  212. data/lib/active_support/log_subscriber.rb +188 -0
  213. data/lib/active_support/logger.rb +55 -0
  214. data/lib/active_support/logger_silence.rb +21 -0
  215. data/lib/active_support/logger_thread_safe_level.rb +50 -0
  216. data/lib/active_support/message_encryptor.rb +374 -0
  217. data/lib/active_support/message_encryptors.rb +193 -0
  218. data/lib/active_support/message_pack/cache_serializer.rb +23 -0
  219. data/lib/active_support/message_pack/extensions.rb +310 -0
  220. data/lib/active_support/message_pack/serializer.rb +63 -0
  221. data/lib/active_support/message_pack.rb +50 -0
  222. data/lib/active_support/message_verifier.rb +377 -0
  223. data/lib/active_support/message_verifiers.rb +189 -0
  224. data/lib/active_support/messages/codec.rb +65 -0
  225. data/lib/active_support/messages/metadata.rb +146 -0
  226. data/lib/active_support/messages/rotation_configuration.rb +23 -0
  227. data/lib/active_support/messages/rotation_coordinator.rb +102 -0
  228. data/lib/active_support/messages/rotator.rb +69 -0
  229. data/lib/active_support/messages/serializer_with_fallback.rb +158 -0
  230. data/lib/active_support/multibyte/chars.rb +188 -0
  231. data/lib/active_support/multibyte/unicode.rb +42 -0
  232. data/lib/active_support/multibyte.rb +27 -0
  233. data/lib/active_support/notifications/fanout.rb +467 -0
  234. data/lib/active_support/notifications/instrumenter.rb +240 -0
  235. data/lib/active_support/notifications.rb +281 -0
  236. data/lib/active_support/number_helper/number_converter.rb +190 -0
  237. data/lib/active_support/number_helper/number_to_currency_converter.rb +46 -0
  238. data/lib/active_support/number_helper/number_to_delimited_converter.rb +30 -0
  239. data/lib/active_support/number_helper/number_to_human_converter.rb +69 -0
  240. data/lib/active_support/number_helper/number_to_human_size_converter.rb +60 -0
  241. data/lib/active_support/number_helper/number_to_percentage_converter.rb +16 -0
  242. data/lib/active_support/number_helper/number_to_phone_converter.rb +60 -0
  243. data/lib/active_support/number_helper/number_to_rounded_converter.rb +59 -0
  244. data/lib/active_support/number_helper/rounding_helper.rb +46 -0
  245. data/lib/active_support/number_helper.rb +479 -0
  246. data/lib/active_support/option_merger.rb +38 -0
  247. data/lib/active_support/ordered_hash.rb +50 -0
  248. data/lib/active_support/ordered_options.rb +141 -25
  249. data/lib/active_support/parameter_filter.rb +157 -0
  250. data/lib/active_support/rails.rb +26 -0
  251. data/lib/active_support/railtie.rb +180 -0
  252. data/lib/active_support/reloader.rb +138 -0
  253. data/lib/active_support/rescuable.rb +176 -0
  254. data/lib/active_support/secure_compare_rotator.rb +58 -0
  255. data/lib/active_support/security_utils.rb +38 -0
  256. data/lib/active_support/string_inquirer.rb +35 -0
  257. data/lib/active_support/structured_event_subscriber.rb +99 -0
  258. data/lib/active_support/subscriber.rb +141 -0
  259. data/lib/active_support/syntax_error_proxy.rb +67 -0
  260. data/lib/active_support/tagged_logging.rb +157 -0
  261. data/lib/active_support/test_case.rb +365 -0
  262. data/lib/active_support/testing/assertions.rb +369 -0
  263. data/lib/active_support/testing/autorun.rb +10 -0
  264. data/lib/active_support/testing/constant_lookup.rb +51 -0
  265. data/lib/active_support/testing/constant_stubbing.rb +54 -0
  266. data/lib/active_support/testing/declarative.rb +28 -0
  267. data/lib/active_support/testing/deprecation.rb +82 -0
  268. data/lib/active_support/testing/error_reporter_assertions.rb +124 -0
  269. data/lib/active_support/testing/event_reporter_assertions.rb +227 -0
  270. data/lib/active_support/testing/file_fixtures.rb +38 -0
  271. data/lib/active_support/testing/isolation.rb +121 -0
  272. data/lib/active_support/testing/method_call_assertions.rb +69 -0
  273. data/lib/active_support/testing/notification_assertions.rb +92 -0
  274. data/lib/active_support/testing/parallelization/server.rb +98 -0
  275. data/lib/active_support/testing/parallelization/worker.rb +107 -0
  276. data/lib/active_support/testing/parallelization.rb +79 -0
  277. data/lib/active_support/testing/parallelize_executor.rb +81 -0
  278. data/lib/active_support/testing/setup_and_teardown.rb +57 -0
  279. data/lib/active_support/testing/stream.rb +41 -0
  280. data/lib/active_support/testing/tagged_logging.rb +27 -0
  281. data/lib/active_support/testing/tests_without_assertions.rb +19 -0
  282. data/lib/active_support/testing/time_helpers.rb +273 -0
  283. data/lib/active_support/time.rb +20 -0
  284. data/lib/active_support/time_with_zone.rb +613 -0
  285. data/lib/active_support/values/time_zone.rb +599 -158
  286. data/lib/active_support/version.rb +7 -6
  287. data/lib/active_support/xml_mini/jdom.rb +175 -0
  288. data/lib/active_support/xml_mini/libxml.rb +80 -0
  289. data/lib/active_support/xml_mini/libxmlsax.rb +83 -0
  290. data/lib/active_support/xml_mini/nokogiri.rb +83 -0
  291. data/lib/active_support/xml_mini/nokogirisax.rb +86 -0
  292. data/lib/active_support/xml_mini/rexml.rb +137 -0
  293. data/lib/active_support/xml_mini.rb +212 -0
  294. data/lib/active_support.rb +122 -10
  295. metadata +524 -93
  296. data/CHANGELOG +0 -283
  297. data/lib/active_support/binding_of_caller.rb +0 -84
  298. data/lib/active_support/breakpoint.rb +0 -523
  299. data/lib/active_support/class_attribute_accessors.rb +0 -57
  300. data/lib/active_support/class_inheritable_attributes.rb +0 -117
  301. data/lib/active_support/clean_logger.rb +0 -36
  302. data/lib/active_support/core_ext/blank.rb +0 -38
  303. data/lib/active_support/core_ext/cgi/escape_skipping_slashes.rb +0 -14
  304. data/lib/active_support/core_ext/cgi.rb +0 -5
  305. data/lib/active_support/core_ext/exception.rb +0 -29
  306. data/lib/active_support/core_ext/integer/even_odd.rb +0 -24
  307. data/lib/active_support/core_ext/object_and_class.rb +0 -44
  308. data/lib/active_support/module_attribute_accessors.rb +0 -57
  309. data/lib/active_support/whiny_nil.rb +0 -38
@@ -0,0 +1,101 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/option_merger"
4
+
5
+ class Object
6
+ # An elegant way to factor duplication out of options passed to a series of
7
+ # method calls. Each method called in the block, with the block variable as
8
+ # the receiver, will have its options merged with the default +options+
9
+ # <tt>Hash</tt> or <tt>Hash</tt>-like object provided. Each method called on
10
+ # the block variable must take an options hash as its final argument.
11
+ #
12
+ # Without <tt>with_options</tt>, this code contains duplication:
13
+ #
14
+ # class Account < ActiveRecord::Base
15
+ # has_many :customers, dependent: :destroy
16
+ # has_many :products, dependent: :destroy
17
+ # has_many :invoices, dependent: :destroy
18
+ # has_many :expenses, dependent: :destroy
19
+ # end
20
+ #
21
+ # Using <tt>with_options</tt>, we can remove the duplication:
22
+ #
23
+ # class Account < ActiveRecord::Base
24
+ # with_options dependent: :destroy do |assoc|
25
+ # assoc.has_many :customers
26
+ # assoc.has_many :products
27
+ # assoc.has_many :invoices
28
+ # assoc.has_many :expenses
29
+ # end
30
+ # end
31
+ #
32
+ # It can also be used with an explicit receiver:
33
+ #
34
+ # I18n.with_options locale: user.locale, scope: 'newsletter' do |i18n|
35
+ # subject i18n.t :subject
36
+ # body i18n.t :body, user_name: user.name
37
+ # end
38
+ #
39
+ # When you don't pass an explicit receiver, it executes the whole block
40
+ # in merging options context:
41
+ #
42
+ # class Account < ActiveRecord::Base
43
+ # with_options dependent: :destroy do
44
+ # has_many :customers
45
+ # has_many :products
46
+ # has_many :invoices
47
+ # has_many :expenses
48
+ # end
49
+ # end
50
+ #
51
+ # <tt>with_options</tt> can also be nested since the call is forwarded to its receiver.
52
+ #
53
+ # NOTE: Each nesting level will merge inherited defaults in addition to their own.
54
+ #
55
+ # class Post < ActiveRecord::Base
56
+ # with_options if: :persisted?, length: { minimum: 50 } do
57
+ # validates :content, if: -> { content.present? }
58
+ # end
59
+ # end
60
+ #
61
+ # The code is equivalent to:
62
+ #
63
+ # validates :content, length: { minimum: 50 }, if: -> { content.present? }
64
+ #
65
+ # Hence the inherited default for +if+ key is ignored.
66
+ #
67
+ # NOTE: You cannot call class methods implicitly inside of +with_options+.
68
+ # You can access these methods using the class name instead:
69
+ #
70
+ # class Phone < ActiveRecord::Base
71
+ # enum :phone_number_type, { home: 0, office: 1, mobile: 2 }
72
+ #
73
+ # with_options presence: true do
74
+ # validates :phone_number_type, inclusion: { in: Phone.phone_number_types.keys }
75
+ # end
76
+ # end
77
+ #
78
+ # When the block argument is omitted, the decorated Object instance is returned:
79
+ #
80
+ # module MyStyledHelpers
81
+ # def styled
82
+ # with_options style: "color: red;"
83
+ # end
84
+ # end
85
+ #
86
+ # styled.link_to "I'm red", "/"
87
+ # # => <a href="/" style="color: red;">I'm red</a>
88
+ #
89
+ # styled.button_tag "I'm red too!"
90
+ # # => <button style="color: red;">I'm red too!</button>
91
+ #
92
+ def with_options(options, &block)
93
+ option_merger = ActiveSupport::OptionMerger.new(self, options)
94
+
95
+ if block
96
+ block.arity.zero? ? option_merger.instance_eval(&block) : block.call(option_merger)
97
+ else
98
+ option_merger
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "object/acts_like"
4
+ require_relative "object/blank"
5
+ require_relative "object/duplicable"
6
+ require_relative "object/deep_dup"
7
+ require_relative "object/try"
8
+ require_relative "object/inclusion"
9
+
10
+ require_relative "object/conversions"
11
+ require_relative "object/instance_variables"
12
+
13
+ require_relative "object/json"
14
+ require_relative "object/to_param"
15
+ require_relative "object/to_query"
16
+ require_relative "object/with"
17
+ require_relative "object/with_options"
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "pathname"
4
+
5
+ class Pathname
6
+ # An Pathname is blank if it's empty:
7
+ #
8
+ # Pathname.new("").blank? # => true
9
+ # Pathname.new(" ").blank? # => false
10
+ # Pathname.new("test").blank? # => false
11
+ #
12
+ # @return [true, false]
13
+ def blank?
14
+ to_s.empty?
15
+ end
16
+
17
+ def present? # :nodoc:
18
+ !to_s.empty?
19
+ end
20
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "pathname"
4
+
5
+ class Pathname
6
+ # Returns the receiver if the named file exists otherwise returns +nil+.
7
+ # <tt>pathname.existence</tt> is equivalent to
8
+ #
9
+ # pathname.exist? ? pathname : nil
10
+ #
11
+ # For example, something like
12
+ #
13
+ # content = pathname.read if pathname.exist?
14
+ #
15
+ # becomes
16
+ #
17
+ # content = pathname.existence&.read
18
+ #
19
+ # @return [Pathname]
20
+ def existence
21
+ self if exist?
22
+ end
23
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "pathname/blank"
4
+ require_relative "pathname/existence"
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveSupport
4
+ module CompareWithRange
5
+ # Extends the default Range#=== to support range comparisons.
6
+ # (1..5) === (1..5) # => true
7
+ # (1..5) === (2..3) # => true
8
+ # (1..5) === (1...6) # => true
9
+ # (1..5) === (2..6) # => false
10
+ #
11
+ # The native Range#=== behavior is untouched.
12
+ # ('a'..'f') === ('c') # => true
13
+ # (5..9) === (11) # => false
14
+ #
15
+ # The given range must be fully bounded, with both start and end.
16
+ def ===(value)
17
+ if value.is_a?(::Range)
18
+ is_backwards_op = value.exclude_end? ? :>= : :>
19
+ return false if value.begin && value.end && value.begin.public_send(is_backwards_op, value.end)
20
+ # 1...10 includes 1..9 but it does not include 1..10.
21
+ # 1..10 includes 1...11 but it does not include 1...12.
22
+ operator = exclude_end? && !value.exclude_end? ? :< : :<=
23
+ value_max = !exclude_end? && value.exclude_end? ? value.max : value.last
24
+ super(value.first) && (self.end.nil? || value_max.public_send(operator, last))
25
+ else
26
+ super
27
+ end
28
+ end
29
+
30
+ # Extends the default Range#include? to support range comparisons.
31
+ # (1..5).include?(1..5) # => true
32
+ # (1..5).include?(2..3) # => true
33
+ # (1..5).include?(1...6) # => true
34
+ # (1..5).include?(2..6) # => false
35
+ #
36
+ # The native Range#include? behavior is untouched.
37
+ # ('a'..'f').include?('c') # => true
38
+ # (5..9).include?(11) # => false
39
+ #
40
+ # The given range must be fully bounded, with both start and end.
41
+ def include?(value)
42
+ if value.is_a?(::Range)
43
+ is_backwards_op = value.exclude_end? ? :>= : :>
44
+ return false if value.begin && value.end && value.begin.public_send(is_backwards_op, value.end)
45
+ # 1...10 includes 1..9 but it does not include 1..10.
46
+ # 1..10 includes 1...11 but it does not include 1...12.
47
+ operator = exclude_end? && !value.exclude_end? ? :< : :<=
48
+ value_max = !exclude_end? && value.exclude_end? ? value.max : value.last
49
+ super(value.first) && (self.end.nil? || value_max.public_send(operator, last))
50
+ else
51
+ super
52
+ end
53
+ end
54
+ end
55
+ end
56
+
57
+ Range.prepend(ActiveSupport::CompareWithRange)
@@ -1,21 +1,62 @@
1
- module ActiveSupport #:nodoc:
2
- module CoreExtensions #:nodoc:
3
- module Range #:nodoc:
4
- # Getting dates in different convenient string representations and other objects
5
- module Conversions
6
- DATE_FORMATS = {
7
- :db => Proc.new { |start, stop| "BETWEEN '#{start.to_s(:db)}' AND '#{stop.to_s(:db)}'" }
8
- }
9
-
10
- def self.included(klass) #:nodoc:
11
- klass.send(:alias_method, :to_default_s, :to_s)
12
- klass.send(:alias_method, :to_s, :to_formatted_s)
13
- end
14
-
15
- def to_formatted_s(format = :default)
16
- DATE_FORMATS[format] ? DATE_FORMATS[format].call(first, last) : to_default_s
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveSupport
4
+ # = \Range With Format
5
+ module RangeWithFormat
6
+ RANGE_FORMATS = {
7
+ db: -> (start, stop) do
8
+ if start && stop
9
+ case start
10
+ when String then "BETWEEN '#{start}' AND '#{stop}'"
11
+ else
12
+ "BETWEEN '#{start.to_fs(:db)}' AND '#{stop.to_fs(:db)}'"
13
+ end
14
+ elsif start
15
+ case start
16
+ when String then ">= '#{start}'"
17
+ else
18
+ ">= '#{start.to_fs(:db)}'"
19
+ end
20
+ elsif stop
21
+ case stop
22
+ when String then "<= '#{stop}'"
23
+ else
24
+ "<= '#{stop.to_fs(:db)}'"
25
+ end
17
26
  end
18
27
  end
28
+ }
29
+
30
+ # Convert range to a formatted string. See RANGE_FORMATS for predefined formats.
31
+ #
32
+ # This method is aliased to <tt>to_formatted_s</tt>.
33
+ #
34
+ # range = (1..100) # => 1..100
35
+ #
36
+ # range.to_s # => "1..100"
37
+ # range.to_fs(:db) # => "BETWEEN '1' AND '100'"
38
+ #
39
+ # range = (1..) # => 1..
40
+ # range.to_fs(:db) # => ">= '1'"
41
+ #
42
+ # range = (..100) # => ..100
43
+ # range.to_fs(:db) # => "<= '100'"
44
+ #
45
+ # == Adding your own range formats to to_fs
46
+ # You can add your own formats to the Range::RANGE_FORMATS hash.
47
+ # Use the format name as the hash key and a Proc instance.
48
+ #
49
+ # # config/initializers/range_formats.rb
50
+ # Range::RANGE_FORMATS[:short] = ->(start, stop) { "Between #{start.to_fs(:db)} and #{stop.to_fs(:db)}" }
51
+ def to_fs(format = :default)
52
+ if formatter = RANGE_FORMATS[format]
53
+ formatter.call(self.begin, self.end)
54
+ else
55
+ to_s
56
+ end
19
57
  end
58
+ alias_method :to_formatted_s, :to_fs
20
59
  end
21
- end
60
+ end
61
+
62
+ Range.prepend(ActiveSupport::RangeWithFormat)
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Range
4
+ unless Range.method_defined?(:overlap?) # Ruby 3.3+
5
+ # Compare two ranges and see if they overlap each other
6
+ # (1..5).overlap?(4..6) # => true
7
+ # (1..5).overlap?(7..9) # => false
8
+ def overlap?(other)
9
+ raise TypeError unless other.is_a? Range
10
+
11
+ self_begin = self.begin
12
+ other_end = other.end
13
+ other_excl = other.exclude_end?
14
+
15
+ return false if _empty_range?(self_begin, other_end, other_excl)
16
+
17
+ other_begin = other.begin
18
+ self_end = self.end
19
+ self_excl = self.exclude_end?
20
+
21
+ return false if _empty_range?(other_begin, self_end, self_excl)
22
+ return true if self_begin == other_begin
23
+
24
+ return false if _empty_range?(self_begin, self_end, self_excl)
25
+ return false if _empty_range?(other_begin, other_end, other_excl)
26
+
27
+ true
28
+ end
29
+
30
+ private
31
+ def _empty_range?(b, e, excl)
32
+ return false if b.nil? || e.nil?
33
+
34
+ comp = b <=> e
35
+ comp.nil? || comp > 0 || (comp == 0 && excl)
36
+ end
37
+ end
38
+
39
+ alias :overlaps? :overlap?
40
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Range
4
+ # Returns the sole item in the range. If there are no items, or more
5
+ # than one item, raises Enumerable::SoleItemExpectedError.
6
+ #
7
+ # (1..1).sole # => 1
8
+ # (2..1).sole # => Enumerable::SoleItemExpectedError: no item found
9
+ # (..1).sole # => Enumerable::SoleItemExpectedError: infinite range cannot represent a sole item
10
+ def sole
11
+ if self.begin.nil? || self.end.nil?
12
+ raise ActiveSupport::EnumerableCoreExt::SoleItemExpectedError, "infinite range '#{inspect}' cannot represent a sole item"
13
+ end
14
+
15
+ super
16
+ end
17
+ end
@@ -1,5 +1,6 @@
1
- require File.dirname(__FILE__) + '/range/conversions'
1
+ # frozen_string_literal: true
2
2
 
3
- class Range #:nodoc:
4
- include ActiveSupport::CoreExtensions::Range::Conversions
5
- end
3
+ require_relative "range/conversions"
4
+ require_relative "range/compare_range"
5
+ require_relative "range/overlap"
6
+ require_relative "range/sole"
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Regexp
4
+ # Returns +true+ if the regexp has the multiline flag set.
5
+ #
6
+ # (/./).multiline? # => false
7
+ # (/./m).multiline? # => true
8
+ #
9
+ # Regexp.new(".").multiline? # => false
10
+ # Regexp.new(".", Regexp::MULTILINE).multiline? # => true
11
+ def multiline?
12
+ options & MULTILINE == MULTILINE
13
+ end
14
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "securerandom"
4
+
5
+ module SecureRandom
6
+ BASE58_ALPHABET = ("0".."9").to_a + ("A".."Z").to_a + ("a".."z").to_a - ["0", "O", "I", "l"]
7
+ BASE36_ALPHABET = ("0".."9").to_a + ("a".."z").to_a
8
+
9
+ # SecureRandom.base58 generates a random base58 string.
10
+ #
11
+ # The argument _n_ specifies the length of the random string to be generated.
12
+ #
13
+ # If _n_ is not specified or is +nil+, 16 is assumed. It may be larger in the future.
14
+ #
15
+ # The result may contain alphanumeric characters except 0, O, I, and l.
16
+ #
17
+ # p SecureRandom.base58 # => "4kUgL2pdQMSCQtjE"
18
+ # p SecureRandom.base58(24) # => "77TMHrHJFvFDwodq8w7Ev2m7"
19
+ if SecureRandom.method(:alphanumeric).parameters.size == 2 # Remove check when Ruby 3.3 is the minimum supported version
20
+ def self.base58(n = 16)
21
+ alphanumeric(n, chars: BASE58_ALPHABET)
22
+ end
23
+ else
24
+ def self.base58(n = 16)
25
+ SecureRandom.random_bytes(n).unpack("C*").map do |byte|
26
+ idx = byte % 64
27
+ idx = SecureRandom.random_number(58) if idx >= 58
28
+ BASE58_ALPHABET[idx]
29
+ end.join
30
+ end
31
+ end
32
+
33
+ # SecureRandom.base36 generates a random base36 string in lowercase.
34
+ #
35
+ # The argument _n_ specifies the length of the random string to be generated.
36
+ #
37
+ # If _n_ is not specified or is +nil+, 16 is assumed. It may be larger in the future.
38
+ # This method can be used over +base58+ if a deterministic case key is necessary.
39
+ #
40
+ # The result will contain alphanumeric characters in lowercase.
41
+ #
42
+ # p SecureRandom.base36 # => "4kugl2pdqmscqtje"
43
+ # p SecureRandom.base36(24) # => "77tmhrhjfvfdwodq8w7ev2m7"
44
+ if SecureRandom.method(:alphanumeric).parameters.size == 2 # Remove check when Ruby 3.3 is the minimum supported version
45
+ def self.base36(n = 16)
46
+ alphanumeric(n, chars: BASE36_ALPHABET)
47
+ end
48
+ else
49
+ def self.base36(n = 16)
50
+ SecureRandom.random_bytes(n).unpack("C*").map do |byte|
51
+ idx = byte % 64
52
+ idx = SecureRandom.random_number(36) if idx >= 36
53
+ BASE36_ALPHABET[idx]
54
+ end.join
55
+ end
56
+ end
57
+ end
@@ -1,58 +1,95 @@
1
- module ActiveSupport #:nodoc:
2
- module CoreExtensions #:nodoc:
3
- module String #:nodoc:
4
- # Makes it easier to access parts of a string, such as specific characters and substrings.
5
- module Access
6
- # Returns the character at the +position+ treating the string as an array (where 0 is the first character).
7
- #
8
- # Examples:
9
- # "hello".at(0) # => "h"
10
- # "hello".at(4) # => "o"
11
- # "hello".at(10) # => nil
12
- def at(position)
13
- self[position, 1]
14
- end
15
-
16
- # Returns the remaining of the string from the +position+ treating the string as an array (where 0 is the first character).
17
- #
18
- # Examples:
19
- # "hello".from(0) # => "hello"
20
- # "hello".from(2) # => "llo"
21
- # "hello".from(10) # => nil
22
- def from(position)
23
- self[position..-1]
24
- end
25
-
26
- # Returns the beginning of the string up to the +position+ treating the string as an array (where 0 is the first character).
27
- #
28
- # Examples:
29
- # "hello".to(0) # => "h"
30
- # "hello".to(2) # => "hel"
31
- # "hello".to(10) # => "hello"
32
- def to(position)
33
- self[0..position]
34
- end
1
+ # frozen_string_literal: true
35
2
 
36
- # Returns the first character of the string or the first +limit+ characters.
37
- #
38
- # Examples:
39
- # "hello".first # => "h"
40
- # "hello".first(2) # => "he"
41
- # "hello".first(10) # => "hello"
42
- def first(limit = 1)
43
- self[0..(limit - 1)]
44
- end
45
-
46
- # Returns the last character of the string or the last +limit+ characters.
47
- #
48
- # Examples:
49
- # "hello".last # => "o"
50
- # "hello".last(2) # => "lo"
51
- # "hello".last(10) # => "hello"
52
- def last(limit = 1)
53
- self[(-limit)..-1]
54
- end
55
- end
56
- end
3
+ class String
4
+ # If you pass a single integer, returns a substring of one character at that
5
+ # position. The first character of the string is at position 0, the next at
6
+ # position 1, and so on. If a range is supplied, a substring containing
7
+ # characters at offsets given by the range is returned. In both cases, if an
8
+ # offset is negative, it is counted from the end of the string. Returns +nil+
9
+ # if the initial offset falls outside the string. Returns an empty string if
10
+ # the beginning of the range is greater than the end of the string.
11
+ #
12
+ # str = "hello"
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) # => ""
19
+ #
20
+ # If a Regexp is given, the matching portion of the string is returned.
21
+ # If a String is given, that given string is returned if it occurs in
22
+ # the string. In both cases, +nil+ is returned if there is no match.
23
+ #
24
+ # str = "hello"
25
+ # str.at(/lo/) # => "lo"
26
+ # str.at(/ol/) # => nil
27
+ # str.at("lo") # => "lo"
28
+ # str.at("ol") # => nil
29
+ def at(position)
30
+ self[position]
57
31
  end
58
- end
32
+
33
+ # Returns a substring from the given position to the end of the string.
34
+ # If the position is negative, it is counted from the end of the string.
35
+ #
36
+ # str = "hello"
37
+ # str.from(0) # => "hello"
38
+ # str.from(3) # => "lo"
39
+ # str.from(-2) # => "lo"
40
+ #
41
+ # You can mix it with +to+ method and do fun things like:
42
+ #
43
+ # str = "hello"
44
+ # str.from(0).to(-1) # => "hello"
45
+ # str.from(1).to(-2) # => "ell"
46
+ def from(position)
47
+ self[position, length]
48
+ end
49
+
50
+ # Returns a substring from the beginning of the string to the given position.
51
+ # If the position is negative, it is counted from the end of the string.
52
+ #
53
+ # str = "hello"
54
+ # str.to(0) # => "h"
55
+ # str.to(3) # => "hell"
56
+ # str.to(-2) # => "hell"
57
+ #
58
+ # You can mix it with +from+ method and do fun things like:
59
+ #
60
+ # str = "hello"
61
+ # str.from(0).to(-1) # => "hello"
62
+ # str.from(1).to(-2) # => "ell"
63
+ def to(position)
64
+ position += size if position < 0
65
+ self[0, position + 1] || +""
66
+ end
67
+
68
+ # Returns the first character. If a limit is supplied, returns a substring
69
+ # from the beginning of the string until it reaches the limit value. If the
70
+ # given limit is greater than or equal to the string length, returns a copy of self.
71
+ #
72
+ # str = "hello"
73
+ # str.first # => "h"
74
+ # str.first(1) # => "h"
75
+ # str.first(2) # => "he"
76
+ # str.first(0) # => ""
77
+ # str.first(6) # => "hello"
78
+ def first(limit = 1)
79
+ self[0, limit] || raise(ArgumentError, "negative limit")
80
+ end
81
+
82
+ # Returns the last character of the string. If a limit is supplied, returns a substring
83
+ # from the end of the string until it reaches the limit value (counting backwards). If
84
+ # the given limit is greater than or equal to the string length, returns a copy of self.
85
+ #
86
+ # str = "hello"
87
+ # str.last # => "o"
88
+ # str.last(1) # => "o"
89
+ # str.last(2) # => "lo"
90
+ # str.last(0) # => ""
91
+ # str.last(6) # => "hello"
92
+ def last(limit = 1)
93
+ self[[length - limit, 0].max, limit] || raise(ArgumentError, "negative limit")
94
+ end
95
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ class String
4
+ # Enables more predictable duck-typing on String-like classes. See <tt>Object#acts_like?</tt>.
5
+ def acts_like_string?
6
+ true
7
+ end
8
+ end