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,3 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cgi"
4
+
1
5
  class Object
2
6
  # Alias of <tt>to_s</tt>.
3
7
  def to_param
@@ -7,7 +11,6 @@ class Object
7
11
  # Converts an object into a string suitable for use as a URL query string,
8
12
  # using the given <tt>key</tt> as the param name.
9
13
  def to_query(key)
10
- require 'cgi' unless defined?(CGI) && defined?(CGI::escape)
11
14
  "#{CGI.escape(key.to_param)}=#{CGI.escape(to_param.to_s)}"
12
15
  end
13
16
  end
@@ -37,7 +40,7 @@ class Array
37
40
  # Calls <tt>to_param</tt> on all its elements and joins the result with
38
41
  # slashes. This is used by <tt>url_for</tt> in Action Pack.
39
42
  def to_param
40
- collect { |e| e.to_param }.join '/'
43
+ collect(&:to_param).join "/"
41
44
  end
42
45
 
43
46
  # Converts an array into a string suitable for use as a URL query string,
@@ -46,7 +49,12 @@ class Array
46
49
  # ['Rails', 'coding'].to_query('hobbies') # => "hobbies%5B%5D=Rails&hobbies%5B%5D=coding"
47
50
  def to_query(key)
48
51
  prefix = "#{key}[]"
49
- collect { |value| value.to_query(prefix) }.join '&'
52
+
53
+ if empty?
54
+ nil.to_query(prefix)
55
+ else
56
+ collect { |value| value.to_query(prefix) }.join "&"
57
+ end
50
58
  end
51
59
  end
52
60
 
@@ -57,19 +65,24 @@ class Hash
57
65
  # {name: 'David', nationality: 'Danish'}.to_query
58
66
  # # => "name=David&nationality=Danish"
59
67
  #
60
- # An optional namespace can be passed to enclose the param names:
68
+ # An optional namespace can be passed to enclose key names:
61
69
  #
62
70
  # {name: 'David', nationality: 'Danish'}.to_query('user')
63
- # # => "user[name]=David&user[nationality]=Danish"
71
+ # # => "user%5Bname%5D=David&user%5Bnationality%5D=Danish"
64
72
  #
65
73
  # The string pairs "key=value" that conform the query string
66
74
  # are sorted lexicographically in ascending order.
67
75
  #
68
76
  # This method is also aliased as +to_param+.
69
77
  def to_query(namespace = nil)
70
- collect do |key, value|
71
- value.to_query(namespace ? "#{namespace}[#{key}]" : key)
72
- end.sort * '&'
78
+ query = filter_map do |key, value|
79
+ unless (value.is_a?(Hash) || value.is_a?(Array)) && value.empty?
80
+ value.to_query(namespace ? "#{namespace}[#{key}]" : key)
81
+ end
82
+ end
83
+
84
+ query.sort! unless namespace.to_s.include?("[]")
85
+ query.join("&")
73
86
  end
74
87
 
75
88
  alias_method :to_param, :to_query
@@ -1,4 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "delegate"
4
+
5
+ module ActiveSupport
6
+ module Tryable # :nodoc:
7
+ def try(*args, &block)
8
+ if args.empty? && block_given?
9
+ if block.arity == 0
10
+ instance_eval(&block)
11
+ else
12
+ yield self
13
+ end
14
+ elsif respond_to?(args.first)
15
+ public_send(*args, &block)
16
+ end
17
+ end
18
+ ruby2_keywords(:try)
19
+
20
+ def try!(*args, &block)
21
+ if args.empty? && block_given?
22
+ if block.arity == 0
23
+ instance_eval(&block)
24
+ else
25
+ yield self
26
+ end
27
+ else
28
+ public_send(*args, &block)
29
+ end
30
+ end
31
+ ruby2_keywords(:try!)
32
+ end
33
+ end
34
+
1
35
  class Object
36
+ include ActiveSupport::Tryable
37
+
38
+ ##
39
+ # :method: try
40
+ #
41
+ # :call-seq:
42
+ # try(*args, &block)
43
+ #
2
44
  # Invokes the public method whose name goes as first argument just like
3
45
  # +public_send+ does, except that if the receiver does not respond to it the
4
46
  # call returns +nil+ rather than raising an exception.
@@ -9,7 +51,23 @@ class Object
9
51
  #
10
52
  # instead of
11
53
  #
12
- # @person ? @person.name : nil
54
+ # @person.name if @person
55
+ #
56
+ # +try+ calls can be chained:
57
+ #
58
+ # @person.try(:spouse).try(:name)
59
+ #
60
+ # instead of
61
+ #
62
+ # @person.spouse.name if @person && @person.spouse
63
+ #
64
+ # +try+ will also return +nil+ if the receiver does not respond to the method:
65
+ #
66
+ # @person.try(:non_existing_method) # => nil
67
+ #
68
+ # instead of
69
+ #
70
+ # @person.non_existing_method if @person.respond_to?(:non_existing_method) # => nil
13
71
  #
14
72
  # +try+ returns +nil+ when called on +nil+ regardless of whether it responds
15
73
  # to the method:
@@ -24,7 +82,7 @@ class Object
24
82
  #
25
83
  # The number of arguments in the signature must match. If the object responds
26
84
  # to the method the call is attempted and +ArgumentError+ is still raised
27
- # otherwise.
85
+ # in case of argument mismatch.
28
86
  #
29
87
  # If +try+ is called without arguments it yields the receiver to a given
30
88
  # block unless it is +nil+:
@@ -33,46 +91,68 @@ class Object
33
91
  # ...
34
92
  # end
35
93
  #
36
- # Please also note that +try+ is defined on +Object+, therefore it won't work
94
+ # You can also call try with a block without accepting an argument, and the block
95
+ # will be instance_eval'ed instead:
96
+ #
97
+ # @person.try { upcase.truncate(50) }
98
+ #
99
+ # Please also note that +try+ is defined on +Object+. Therefore, it won't work
37
100
  # with instances of classes that do not have +Object+ among their ancestors,
38
- # like direct subclasses of +BasicObject+. For example, using +try+ with
39
- # +SimpleDelegator+ will delegate +try+ to the target instead of calling it on
40
- # delegator itself.
41
- def try(*a, &b)
42
- if a.empty? && block_given?
43
- yield self
44
- else
45
- public_send(*a, &b) if respond_to?(a.first)
46
- end
47
- end
101
+ # like direct subclasses of +BasicObject+.
48
102
 
49
- # Same as #try, but will raise a NoMethodError exception if the receiving is not nil and
50
- # does not implemented the tried method.
51
- def try!(*a, &b)
52
- if a.empty? && block_given?
53
- yield self
54
- else
55
- public_send(*a, &b)
56
- end
57
- end
103
+ ##
104
+ # :method: try!
105
+ #
106
+ # :call-seq:
107
+ # try!(*args, &block)
108
+ #
109
+ # Same as #try, but raises a +NoMethodError+ exception if the receiver is
110
+ # not +nil+ and does not implement the tried method.
111
+ #
112
+ # "a".try!(:upcase) # => "A"
113
+ # nil.try!(:upcase) # => nil
114
+ # 123.try!(:upcase) # => NoMethodError: undefined method `upcase' for 123:Integer
115
+ end
116
+
117
+ class Delegator
118
+ include ActiveSupport::Tryable
119
+
120
+ ##
121
+ # :method: try
122
+ #
123
+ # :call-seq:
124
+ # try(*args, &block)
125
+ #
126
+ # See Object#try
127
+
128
+ ##
129
+ # :method: try!
130
+ #
131
+ # :call-seq:
132
+ # try!(*args, &block)
133
+ #
134
+ # See Object#try!
58
135
  end
59
136
 
60
137
  class NilClass
61
138
  # Calling +try+ on +nil+ always returns +nil+.
62
- # It becomes specially helpful when navigating through associations that may return +nil+.
139
+ # It becomes especially helpful when navigating through associations that may return +nil+.
63
140
  #
64
141
  # nil.try(:name) # => nil
65
142
  #
66
143
  # Without +try+
67
- # @person && !@person.children.blank? && @person.children.first.name
144
+ # @person && @person.children.any? && @person.children.first.name
68
145
  #
69
146
  # With +try+
70
147
  # @person.try(:children).try(:first).try(:name)
71
- def try(*args)
148
+ def try(*)
72
149
  nil
73
150
  end
74
151
 
75
- def try!(*args)
152
+ # Calling +try!+ on +nil+ always returns +nil+.
153
+ #
154
+ # nil.try!(:name) # => nil
155
+ def try!(*)
76
156
  nil
77
157
  end
78
158
  end
@@ -1,4 +1,6 @@
1
- require 'active_support/option_merger'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/option_merger"
2
4
 
3
5
  class Object
4
6
  # An elegant way to factor duplication out of options passed to a series of
@@ -7,7 +9,7 @@ class Object
7
9
  # provided. Each method called on the block variable must take an options
8
10
  # hash as its final argument.
9
11
  #
10
- # Without <tt>with_options></tt>, this code contains duplication:
12
+ # Without <tt>with_options</tt>, this code contains duplication:
11
13
  #
12
14
  # class Account < ActiveRecord::Base
13
15
  # has_many :customers, dependent: :destroy
@@ -34,9 +36,66 @@ class Object
34
36
  # body i18n.t :body, user_name: user.name
35
37
  # end
36
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
+ #
37
51
  # <tt>with_options</tt> can also be nested since the call is forwarded to its receiver.
38
- # Each nesting level will merge inherited defaults in addition to their own.
39
- def with_options(options)
40
- yield ActiveSupport::OptionMerger.new(self, options)
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
41
100
  end
42
101
  end
@@ -1,14 +1,16 @@
1
- require 'active_support/core_ext/object/acts_like'
2
- require 'active_support/core_ext/object/blank'
3
- require 'active_support/core_ext/object/duplicable'
4
- require 'active_support/core_ext/object/deep_dup'
5
- require 'active_support/core_ext/object/try'
6
- require 'active_support/core_ext/object/inclusion'
1
+ # frozen_string_literal: true
7
2
 
8
- require 'active_support/core_ext/object/conversions'
9
- require 'active_support/core_ext/object/instance_variables'
3
+ require "active_support/core_ext/object/acts_like"
4
+ require "active_support/core_ext/object/blank"
5
+ require "active_support/core_ext/object/duplicable"
6
+ require "active_support/core_ext/object/deep_dup"
7
+ require "active_support/core_ext/object/try"
8
+ require "active_support/core_ext/object/inclusion"
10
9
 
11
- require 'active_support/core_ext/object/to_json'
12
- require 'active_support/core_ext/object/to_param'
13
- require 'active_support/core_ext/object/to_query'
14
- require 'active_support/core_ext/object/with_options'
10
+ require "active_support/core_ext/object/conversions"
11
+ require "active_support/core_ext/object/instance_variables"
12
+
13
+ require "active_support/core_ext/object/json"
14
+ require "active_support/core_ext/object/to_param"
15
+ require "active_support/core_ext/object/to_query"
16
+ require "active_support/core_ext/object/with_options"
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Pathname
4
+ # Returns the receiver if the named file exists otherwise returns +nil+.
5
+ # <tt>pathname.existence</tt> is equivalent to
6
+ #
7
+ # pathname.exist? ? pathname : nil
8
+ #
9
+ # For example, something like
10
+ #
11
+ # content = pathname.read if pathname.exist?
12
+ #
13
+ # becomes
14
+ #
15
+ # content = pathname.existence&.read
16
+ #
17
+ # @return [Pathname]
18
+ def existence
19
+ self if exist?
20
+ end
21
+ end
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/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,19 +1,41 @@
1
- class Range
2
- RANGE_FORMATS = {
3
- :db => Proc.new { |start, stop| "BETWEEN '#{start.to_s(:db)}' AND '#{stop.to_s(:db)}'" }
4
- }
1
+ # frozen_string_literal: true
5
2
 
6
- # Gives a human readable format of the range.
7
- #
8
- # (1..100).to_formatted_s # => "1..100"
9
- def to_formatted_s(format = :default)
10
- if formatter = RANGE_FORMATS[format]
11
- formatter.call(first, last)
12
- else
13
- to_default_s
3
+ module ActiveSupport
4
+ module RangeWithFormat
5
+ RANGE_FORMATS = {
6
+ db: -> (start, stop) do
7
+ case start
8
+ when String then "BETWEEN '#{start}' AND '#{stop}'"
9
+ else
10
+ "BETWEEN '#{start.to_fs(:db)}' AND '#{stop.to_fs(:db)}'"
11
+ end
12
+ end
13
+ }
14
+
15
+ # Convert range to a formatted string. See RANGE_FORMATS for predefined formats.
16
+ #
17
+ # This method is aliased to <tt>to_formatted_s</tt>.
18
+ #
19
+ # range = (1..100) # => 1..100
20
+ #
21
+ # range.to_s # => "1..100"
22
+ # range.to_fs(:db) # => "BETWEEN '1' AND '100'"
23
+ #
24
+ # == Adding your own range formats to to_s
25
+ # You can add your own formats to the Range::RANGE_FORMATS hash.
26
+ # Use the format name as the hash key and a Proc instance.
27
+ #
28
+ # # config/initializers/range_formats.rb
29
+ # Range::RANGE_FORMATS[:short] = ->(start, stop) { "Between #{start.to_fs(:db)} and #{stop.to_fs(:db)}" }
30
+ def to_fs(format = :default)
31
+ if formatter = RANGE_FORMATS[format]
32
+ formatter.call(first, last)
33
+ else
34
+ to_s
35
+ end
14
36
  end
37
+ alias_method :to_formatted_s, :to_fs
15
38
  end
16
-
17
- alias_method :to_default_s, :to_s
18
- alias_method :to_s, :to_formatted_s
19
39
  end
40
+
41
+ Range.prepend(ActiveSupport::RangeWithFormat)
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveSupport
4
+ module DeprecatedRangeWithFormat # :nodoc:
5
+ NOT_SET = Object.new # :nodoc:
6
+ def to_s(format = NOT_SET)
7
+ if formatter = RangeWithFormat::RANGE_FORMATS[format]
8
+ ActiveSupport::Deprecation.warn(
9
+ "Range#to_s(#{format.inspect}) is deprecated. Please use Range#to_fs(#{format.inspect}) instead."
10
+ )
11
+ formatter.call(first, last)
12
+ elsif format == NOT_SET
13
+ super()
14
+ else
15
+ ActiveSupport::Deprecation.warn(
16
+ "Range#to_s(#{format.inspect}) is deprecated. Please use Range#to_fs(#{format.inspect}) instead."
17
+ )
18
+ super()
19
+ end
20
+ end
21
+ alias_method :to_default_s, :to_s
22
+ deprecate :to_default_s
23
+ end
24
+ end
25
+
26
+ Range.prepend(ActiveSupport::DeprecatedRangeWithFormat)
@@ -1,23 +1,24 @@
1
- require 'active_support/core_ext/module/aliasing'
1
+ # frozen_string_literal: true
2
2
 
3
- class Range #:nodoc:
3
+ require "active_support/time_with_zone"
4
4
 
5
- def each_with_time_with_zone(&block)
6
- ensure_iteration_allowed
7
- each_without_time_with_zone(&block)
8
- end
9
- alias_method_chain :each, :time_with_zone
10
-
11
- def step_with_time_with_zone(n = 1, &block)
12
- ensure_iteration_allowed
13
- step_without_time_with_zone(n, &block)
14
- end
15
- alias_method_chain :step, :time_with_zone
5
+ module ActiveSupport
6
+ module EachTimeWithZone # :nodoc:
7
+ def each(&block)
8
+ ensure_iteration_allowed
9
+ super
10
+ end
16
11
 
17
- private
18
- def ensure_iteration_allowed
19
- if first.is_a?(Time)
20
- raise TypeError, "can't iterate from #{first.class}"
12
+ def step(n = 1, &block)
13
+ ensure_iteration_allowed
14
+ super
21
15
  end
16
+
17
+ private
18
+ def ensure_iteration_allowed
19
+ raise TypeError, "can't iterate from #{first.class}" if first.is_a?(TimeWithZone)
20
+ end
22
21
  end
23
22
  end
23
+
24
+ Range.prepend(ActiveSupport::EachTimeWithZone)
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ # frozen_string_literal: true
4
+
5
+ ActiveSupport::Deprecation.warn(<<-MSG.squish)
6
+ `active_support/core_ext/range/include_time_with_zone` is deprecated and will be removed in Rails 7.1.
7
+ MSG
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Range
2
4
  # Compare two ranges and see if they overlap each other
3
5
  # (1..5).overlaps?(4..6) # => true
@@ -1,4 +1,7 @@
1
- require 'active_support/core_ext/range/conversions'
2
- require 'active_support/core_ext/range/include_range'
3
- require 'active_support/core_ext/range/overlaps'
4
- require 'active_support/core_ext/range/each'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/range/conversions"
4
+ require "active_support/core_ext/range/deprecated_conversions" unless ENV["RAILS_DISABLE_DEPRECATED_TO_S_CONVERSION"]
5
+ require "active_support/core_ext/range/compare_range"
6
+ require "active_support/core_ext/range/overlaps"
7
+ require "active_support/core_ext/range/each"
@@ -1,4 +1,13 @@
1
- class Regexp #:nodoc:
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
2
11
  def multiline?
3
12
  options & MULTILINE == MULTILINE
4
13
  end
@@ -0,0 +1,45 @@
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
+ def self.base58(n = 16)
20
+ SecureRandom.random_bytes(n).unpack("C*").map do |byte|
21
+ idx = byte % 64
22
+ idx = SecureRandom.random_number(58) if idx >= 58
23
+ BASE58_ALPHABET[idx]
24
+ end.join
25
+ end
26
+
27
+ # SecureRandom.base36 generates a random base36 string in lowercase.
28
+ #
29
+ # The argument _n_ specifies the length of the random string to be generated.
30
+ #
31
+ # If _n_ is not specified or is +nil+, 16 is assumed. It may be larger in the future.
32
+ # This method can be used over +base58+ if a deterministic case key is necessary.
33
+ #
34
+ # The result will contain alphanumeric characters in lowercase.
35
+ #
36
+ # p SecureRandom.base36 # => "4kugl2pdqmscqtje"
37
+ # p SecureRandom.base36(24) # => "77tmhrhjfvfdwodq8w7ev2m7"
38
+ def self.base36(n = 16)
39
+ SecureRandom.random_bytes(n).unpack("C*").map do |byte|
40
+ idx = byte % 64
41
+ idx = SecureRandom.random_number(36) if idx >= 36
42
+ BASE36_ALPHABET[idx]
43
+ end.join
44
+ end
45
+ end