activesupport 5.1.7 → 7.0.4.1

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 (279) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +259 -585
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +6 -5
  5. data/lib/active_support/actionable_error.rb +48 -0
  6. data/lib/active_support/all.rb +2 -0
  7. data/lib/active_support/array_inquirer.rb +4 -2
  8. data/lib/active_support/backtrace_cleaner.rb +33 -5
  9. data/lib/active_support/benchmarkable.rb +5 -3
  10. data/lib/active_support/builder.rb +2 -0
  11. data/lib/active_support/cache/file_store.rb +50 -43
  12. data/lib/active_support/cache/mem_cache_store.rb +194 -67
  13. data/lib/active_support/cache/memory_store.rb +70 -34
  14. data/lib/active_support/cache/null_store.rb +18 -3
  15. data/lib/active_support/cache/redis_cache_store.rb +474 -0
  16. data/lib/active_support/cache/strategy/local_cache.rb +73 -50
  17. data/lib/active_support/cache/strategy/local_cache_middleware.rb +2 -0
  18. data/lib/active_support/cache.rb +556 -220
  19. data/lib/active_support/callbacks.rb +264 -159
  20. data/lib/active_support/code_generator.rb +65 -0
  21. data/lib/active_support/concern.rb +81 -8
  22. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +16 -0
  23. data/lib/active_support/concurrency/share_lock.rb +4 -3
  24. data/lib/active_support/configurable.rb +17 -16
  25. data/lib/active_support/configuration_file.rb +51 -0
  26. data/lib/active_support/core_ext/array/access.rb +18 -8
  27. data/lib/active_support/core_ext/array/conversions.rb +20 -17
  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 +8 -6
  32. data/lib/active_support/core_ext/array/inquiry.rb +4 -2
  33. data/lib/active_support/core_ext/array/wrap.rb +2 -0
  34. data/lib/active_support/core_ext/array.rb +4 -1
  35. data/lib/active_support/core_ext/benchmark.rb +4 -2
  36. data/lib/active_support/core_ext/big_decimal/conversions.rb +3 -1
  37. data/lib/active_support/core_ext/big_decimal.rb +2 -0
  38. data/lib/active_support/core_ext/class/attribute.rb +50 -47
  39. data/lib/active_support/core_ext/class/attribute_accessors.rb +2 -0
  40. data/lib/active_support/core_ext/class/subclasses.rb +10 -24
  41. data/lib/active_support/core_ext/class.rb +2 -0
  42. data/lib/active_support/core_ext/date/acts_like.rb +2 -0
  43. data/lib/active_support/core_ext/date/blank.rb +3 -1
  44. data/lib/active_support/core_ext/date/calculations.rb +17 -14
  45. data/lib/active_support/core_ext/date/conversions.rb +24 -22
  46. data/lib/active_support/core_ext/date/deprecated_conversions.rb +26 -0
  47. data/lib/active_support/core_ext/date/zones.rb +2 -0
  48. data/lib/active_support/core_ext/date.rb +3 -0
  49. data/lib/active_support/core_ext/date_and_time/calculations.rb +65 -41
  50. data/lib/active_support/core_ext/date_and_time/compatibility.rb +18 -1
  51. data/lib/active_support/core_ext/date_and_time/zones.rb +2 -1
  52. data/lib/active_support/core_ext/date_time/acts_like.rb +2 -0
  53. data/lib/active_support/core_ext/date_time/blank.rb +3 -1
  54. data/lib/active_support/core_ext/date_time/calculations.rb +3 -1
  55. data/lib/active_support/core_ext/date_time/compatibility.rb +7 -5
  56. data/lib/active_support/core_ext/date_time/conversions.rb +15 -14
  57. data/lib/active_support/core_ext/date_time/deprecated_conversions.rb +22 -0
  58. data/lib/active_support/core_ext/date_time.rb +3 -0
  59. data/lib/active_support/core_ext/digest/uuid.rb +42 -14
  60. data/lib/active_support/core_ext/digest.rb +3 -0
  61. data/lib/active_support/core_ext/enumerable.rb +244 -72
  62. data/lib/active_support/core_ext/file/atomic.rb +6 -2
  63. data/lib/active_support/core_ext/file.rb +2 -0
  64. data/lib/active_support/core_ext/hash/conversions.rb +7 -6
  65. data/lib/active_support/core_ext/hash/deep_merge.rb +8 -12
  66. data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
  67. data/lib/active_support/core_ext/hash/except.rb +4 -2
  68. data/lib/active_support/core_ext/hash/indifferent_access.rb +5 -3
  69. data/lib/active_support/core_ext/hash/keys.rb +4 -31
  70. data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
  71. data/lib/active_support/core_ext/hash/slice.rb +8 -29
  72. data/lib/active_support/core_ext/hash.rb +3 -2
  73. data/lib/active_support/core_ext/integer/inflections.rb +2 -0
  74. data/lib/active_support/core_ext/integer/multiple.rb +3 -1
  75. data/lib/active_support/core_ext/integer/time.rb +7 -14
  76. data/lib/active_support/core_ext/integer.rb +2 -0
  77. data/lib/active_support/core_ext/kernel/concern.rb +2 -0
  78. data/lib/active_support/core_ext/kernel/reporting.rb +6 -4
  79. data/lib/active_support/core_ext/kernel/singleton_class.rb +3 -1
  80. data/lib/active_support/core_ext/kernel.rb +2 -1
  81. data/lib/active_support/core_ext/load_error.rb +3 -8
  82. data/lib/active_support/core_ext/module/aliasing.rb +2 -0
  83. data/lib/active_support/core_ext/module/anonymous.rb +2 -0
  84. data/lib/active_support/core_ext/module/attr_internal.rb +4 -2
  85. data/lib/active_support/core_ext/module/attribute_accessors.rb +46 -56
  86. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +36 -27
  87. data/lib/active_support/core_ext/module/concerning.rb +15 -10
  88. data/lib/active_support/core_ext/module/delegation.rb +97 -58
  89. data/lib/active_support/core_ext/module/deprecation.rb +2 -0
  90. data/lib/active_support/core_ext/module/introspection.rb +18 -15
  91. data/lib/active_support/core_ext/module/redefine_method.rb +40 -0
  92. data/lib/active_support/core_ext/module/remove_method.rb +5 -23
  93. data/lib/active_support/core_ext/module.rb +3 -1
  94. data/lib/active_support/core_ext/name_error.rb +30 -2
  95. data/lib/active_support/core_ext/numeric/bytes.rb +2 -0
  96. data/lib/active_support/core_ext/numeric/conversions.rb +134 -129
  97. data/lib/active_support/core_ext/numeric/deprecated_conversions.rb +60 -0
  98. data/lib/active_support/core_ext/numeric/time.rb +7 -15
  99. data/lib/active_support/core_ext/numeric.rb +3 -1
  100. data/lib/active_support/core_ext/object/acts_like.rb +41 -6
  101. data/lib/active_support/core_ext/object/blank.rb +15 -5
  102. data/lib/active_support/core_ext/object/conversions.rb +2 -0
  103. data/lib/active_support/core_ext/object/deep_dup.rb +3 -1
  104. data/lib/active_support/core_ext/object/duplicable.rb +16 -110
  105. data/lib/active_support/core_ext/object/inclusion.rb +2 -0
  106. data/lib/active_support/core_ext/object/instance_variables.rb +2 -0
  107. data/lib/active_support/core_ext/object/json.rb +51 -26
  108. data/lib/active_support/core_ext/object/to_param.rb +2 -0
  109. data/lib/active_support/core_ext/object/to_query.rb +4 -2
  110. data/lib/active_support/core_ext/object/try.rb +26 -14
  111. data/lib/active_support/core_ext/object/with_options.rb +24 -3
  112. data/lib/active_support/core_ext/object.rb +2 -0
  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 +35 -25
  117. data/lib/active_support/core_ext/range/deprecated_conversions.rb +26 -0
  118. data/lib/active_support/core_ext/range/each.rb +6 -3
  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 +3 -1
  121. data/lib/active_support/core_ext/range.rb +4 -1
  122. data/lib/active_support/core_ext/regexp.rb +10 -5
  123. data/lib/active_support/core_ext/securerandom.rb +25 -3
  124. data/lib/active_support/core_ext/string/access.rb +7 -16
  125. data/lib/active_support/core_ext/string/behavior.rb +2 -0
  126. data/lib/active_support/core_ext/string/conversions.rb +5 -2
  127. data/lib/active_support/core_ext/string/exclude.rb +2 -0
  128. data/lib/active_support/core_ext/string/filters.rb +44 -1
  129. data/lib/active_support/core_ext/string/indent.rb +2 -0
  130. data/lib/active_support/core_ext/string/inflections.rb +69 -16
  131. data/lib/active_support/core_ext/string/inquiry.rb +4 -1
  132. data/lib/active_support/core_ext/string/multibyte.rb +9 -4
  133. data/lib/active_support/core_ext/string/output_safety.rb +135 -27
  134. data/lib/active_support/core_ext/string/starts_ends_with.rb +4 -2
  135. data/lib/active_support/core_ext/string/strip.rb +5 -1
  136. data/lib/active_support/core_ext/string/zones.rb +2 -0
  137. data/lib/active_support/core_ext/string.rb +2 -0
  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 +2 -0
  141. data/lib/active_support/core_ext/time/calculations.rb +81 -24
  142. data/lib/active_support/core_ext/time/compatibility.rb +4 -2
  143. data/lib/active_support/core_ext/time/conversions.rb +17 -12
  144. data/lib/active_support/core_ext/time/deprecated_conversions.rb +22 -0
  145. data/lib/active_support/core_ext/time/zones.rb +12 -25
  146. data/lib/active_support/core_ext/time.rb +3 -0
  147. data/lib/active_support/core_ext/uri.rb +4 -23
  148. data/lib/active_support/core_ext.rb +4 -1
  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 +2 -0
  152. data/lib/active_support/dependencies/interlock.rb +12 -18
  153. data/lib/active_support/dependencies/require_dependency.rb +28 -0
  154. data/lib/active_support/dependencies.rb +59 -715
  155. data/lib/active_support/deprecation/behaviors.rb +48 -13
  156. data/lib/active_support/deprecation/constant_accessor.rb +4 -2
  157. data/lib/active_support/deprecation/disallowed.rb +56 -0
  158. data/lib/active_support/deprecation/instance_delegator.rb +2 -1
  159. data/lib/active_support/deprecation/method_wrappers.rb +29 -21
  160. data/lib/active_support/deprecation/proxy_wrappers.rb +34 -8
  161. data/lib/active_support/deprecation/reporting.rb +54 -9
  162. data/lib/active_support/deprecation.rb +10 -3
  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 +9 -9
  166. data/lib/active_support/duration/iso8601_serializer.rb +29 -15
  167. data/lib/active_support/duration.rb +158 -72
  168. data/lib/active_support/encrypted_configuration.rb +56 -0
  169. data/lib/active_support/encrypted_file.rb +129 -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 +87 -122
  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 +46 -21
  176. data/lib/active_support/executor/test_helper.rb +7 -0
  177. data/lib/active_support/executor.rb +2 -0
  178. data/lib/active_support/file_update_checker.rb +2 -1
  179. data/lib/active_support/fork_tracker.rb +71 -0
  180. data/lib/active_support/gem_version.rb +7 -5
  181. data/lib/active_support/gzip.rb +2 -0
  182. data/lib/active_support/hash_with_indifferent_access.rb +126 -42
  183. data/lib/active_support/html_safe_translation.rb +43 -0
  184. data/lib/active_support/i18n.rb +5 -1
  185. data/lib/active_support/i18n_railtie.rb +19 -14
  186. data/lib/active_support/inflections.rb +2 -0
  187. data/lib/active_support/inflector/inflections.rb +41 -14
  188. data/lib/active_support/inflector/methods.rb +73 -87
  189. data/lib/active_support/inflector/transliterate.rb +56 -18
  190. data/lib/active_support/inflector.rb +2 -0
  191. data/lib/active_support/isolated_execution_state.rb +72 -0
  192. data/lib/active_support/json/decoding.rb +27 -26
  193. data/lib/active_support/json/encoding.rb +16 -6
  194. data/lib/active_support/json.rb +2 -0
  195. data/lib/active_support/key_generator.rb +25 -38
  196. data/lib/active_support/lazy_load_hooks.rb +35 -6
  197. data/lib/active_support/locale/en.rb +33 -0
  198. data/lib/active_support/locale/en.yml +8 -4
  199. data/lib/active_support/log_subscriber/test_helper.rb +4 -2
  200. data/lib/active_support/log_subscriber.rb +54 -13
  201. data/lib/active_support/logger.rb +4 -17
  202. data/lib/active_support/logger_silence.rb +13 -20
  203. data/lib/active_support/logger_thread_safe_level.rb +48 -10
  204. data/lib/active_support/message_encryptor.rb +111 -37
  205. data/lib/active_support/message_verifier.rb +124 -21
  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 +19 -76
  210. data/lib/active_support/multibyte/unicode.rb +9 -331
  211. data/lib/active_support/multibyte.rb +3 -1
  212. data/lib/active_support/notifications/fanout.rb +165 -37
  213. data/lib/active_support/notifications/instrumenter.rb +92 -11
  214. data/lib/active_support/notifications.rb +96 -30
  215. data/lib/active_support/number_helper/number_converter.rb +8 -9
  216. data/lib/active_support/number_helper/number_to_currency_converter.rb +14 -12
  217. data/lib/active_support/number_helper/number_to_delimited_converter.rb +6 -3
  218. data/lib/active_support/number_helper/number_to_human_converter.rb +6 -3
  219. data/lib/active_support/number_helper/number_to_human_size_converter.rb +7 -4
  220. data/lib/active_support/number_helper/number_to_percentage_converter.rb +5 -1
  221. data/lib/active_support/number_helper/number_to_phone_converter.rb +6 -3
  222. data/lib/active_support/number_helper/number_to_rounded_converter.rb +14 -27
  223. data/lib/active_support/number_helper/rounding_helper.rb +16 -34
  224. data/lib/active_support/number_helper.rb +38 -12
  225. data/lib/active_support/option_merger.rb +19 -6
  226. data/lib/active_support/ordered_hash.rb +4 -2
  227. data/lib/active_support/ordered_options.rb +18 -6
  228. data/lib/active_support/parameter_filter.rb +138 -0
  229. data/lib/active_support/per_thread_registry.rb +8 -1
  230. data/lib/active_support/proxy_object.rb +2 -0
  231. data/lib/active_support/rails.rb +3 -10
  232. data/lib/active_support/railtie.rb +112 -11
  233. data/lib/active_support/reloader.rb +12 -11
  234. data/lib/active_support/rescuable.rb +19 -18
  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 +26 -15
  238. data/lib/active_support/string_inquirer.rb +4 -3
  239. data/lib/active_support/subscriber.rb +81 -42
  240. data/lib/active_support/tagged_logging.rb +45 -9
  241. data/lib/active_support/test_case.rb +86 -2
  242. data/lib/active_support/testing/assertions.rb +89 -21
  243. data/lib/active_support/testing/autorun.rb +2 -0
  244. data/lib/active_support/testing/constant_lookup.rb +2 -0
  245. data/lib/active_support/testing/declarative.rb +2 -0
  246. data/lib/active_support/testing/deprecation.rb +54 -2
  247. data/lib/active_support/testing/file_fixtures.rb +4 -0
  248. data/lib/active_support/testing/isolation.rb +6 -4
  249. data/lib/active_support/testing/method_call_assertions.rb +34 -5
  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 +12 -7
  255. data/lib/active_support/testing/stream.rb +6 -7
  256. data/lib/active_support/testing/tagged_logging.rb +3 -1
  257. data/lib/active_support/testing/time_helpers.rb +91 -15
  258. data/lib/active_support/time.rb +2 -0
  259. data/lib/active_support/time_with_zone.rb +168 -56
  260. data/lib/active_support/values/time_zone.rb +85 -37
  261. data/lib/active_support/version.rb +3 -1
  262. data/lib/active_support/xml_mini/jdom.rb +6 -5
  263. data/lib/active_support/xml_mini/libxml.rb +9 -7
  264. data/lib/active_support/xml_mini/libxmlsax.rb +7 -5
  265. data/lib/active_support/xml_mini/nokogiri.rb +8 -6
  266. data/lib/active_support/xml_mini/nokogirisax.rb +6 -4
  267. data/lib/active_support/xml_mini/rexml.rb +13 -4
  268. data/lib/active_support/xml_mini.rb +10 -15
  269. data/lib/active_support.rb +30 -9
  270. metadata +76 -35
  271. data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -7
  272. data/lib/active_support/core_ext/hash/compact.rb +0 -27
  273. data/lib/active_support/core_ext/hash/transform_values.rb +0 -30
  274. data/lib/active_support/core_ext/kernel/agnostics.rb +0 -11
  275. data/lib/active_support/core_ext/marshal.rb +0 -22
  276. data/lib/active_support/core_ext/module/reachable.rb +0 -8
  277. data/lib/active_support/core_ext/numeric/inquiry.rb +0 -26
  278. data/lib/active_support/core_ext/range/include_range.rb +0 -23
  279. data/lib/active_support/values/unicode_tables.dat +0 -0
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/concern"
2
4
 
3
5
  class Module
@@ -20,7 +22,7 @@ class Module
20
22
  #
21
23
  # == Using comments:
22
24
  #
23
- # class Todo
25
+ # class Todo < ApplicationRecord
24
26
  # # Other todo implementation
25
27
  # # ...
26
28
  #
@@ -28,7 +30,6 @@ class Module
28
30
  # has_many :events
29
31
  #
30
32
  # before_create :track_creation
31
- # after_destroy :track_deletion
32
33
  #
33
34
  # private
34
35
  # def track_creation
@@ -40,7 +41,7 @@ class Module
40
41
  #
41
42
  # Noisy syntax.
42
43
  #
43
- # class Todo
44
+ # class Todo < ApplicationRecord
44
45
  # # Other todo implementation
45
46
  # # ...
46
47
  #
@@ -50,7 +51,6 @@ class Module
50
51
  # included do
51
52
  # has_many :events
52
53
  # before_create :track_creation
53
- # after_destroy :track_deletion
54
54
  # end
55
55
  #
56
56
  # private
@@ -68,7 +68,7 @@ class Module
68
68
  # increased overhead can be a reasonable tradeoff even if it reduces our
69
69
  # at-a-glance perception of how things work.
70
70
  #
71
- # class Todo
71
+ # class Todo < ApplicationRecord
72
72
  # # Other todo implementation
73
73
  # # ...
74
74
  #
@@ -80,7 +80,7 @@ class Module
80
80
  # By quieting the mix-in noise, we arrive at a natural, low-ceremony way to
81
81
  # separate bite-sized concerns.
82
82
  #
83
- # class Todo
83
+ # class Todo < ApplicationRecord
84
84
  # # Other todo implementation
85
85
  # # ...
86
86
  #
@@ -88,7 +88,6 @@ class Module
88
88
  # included do
89
89
  # has_many :events
90
90
  # before_create :track_creation
91
- # after_destroy :track_deletion
92
91
  # end
93
92
  #
94
93
  # private
@@ -99,16 +98,22 @@ class Module
99
98
  # end
100
99
  #
101
100
  # Todo.ancestors
102
- # # => [Todo, Todo::EventTracking, Object]
101
+ # # => [Todo, Todo::EventTracking, ApplicationRecord, Object]
103
102
  #
104
103
  # This small step has some wonderful ripple effects. We can
105
104
  # * grok the behavior of our class in one glance,
106
105
  # * clean up monolithic junk-drawer classes by separating their concerns, and
107
106
  # * stop leaning on protected/private for crude "this is internal stuff" modularity.
107
+ #
108
+ # === Prepending concerning
109
+ #
110
+ # <tt>concerning</tt> supports a <tt>prepend: true</tt> argument which will <tt>prepend</tt> the
111
+ # concern instead of using <tt>include</tt> for it.
108
112
  module Concerning
109
113
  # Define a new concern and mix it in.
110
- def concerning(topic, &block)
111
- include concern(topic, &block)
114
+ def concerning(topic, prepend: false, &block)
115
+ method = prepend ? :prepend : :include
116
+ __send__(method, concern(topic, &block))
112
117
  end
113
118
 
114
119
  # A low-cruft shortcut to define a concern.
@@ -1,5 +1,6 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "set"
2
- require "active_support/core_ext/regexp"
3
4
 
4
5
  class Module
5
6
  # Error generated by +delegate+ when a method is called on +nil+ and +allow_nil+
@@ -18,10 +19,11 @@ class Module
18
19
  # public methods as your own.
19
20
  #
20
21
  # ==== Options
21
- # * <tt>:to</tt> - Specifies the target object
22
+ # * <tt>:to</tt> - Specifies the target object name as a symbol or string
22
23
  # * <tt>:prefix</tt> - Prefixes the new method with the target name or a custom prefix
23
- # * <tt>:allow_nil</tt> - if set to true, prevents a +Module::DelegationError+
24
+ # * <tt>:allow_nil</tt> - If set to true, prevents a +Module::DelegationError+
24
25
  # from being raised
26
+ # * <tt>:private</tt> - If set to true, changes method visibility to private
25
27
  #
26
28
  # The macro receives one or more method names (specified as symbols or
27
29
  # strings) and the name of the target object via the <tt>:to</tt> option
@@ -112,12 +114,26 @@ class Module
112
114
  # invoice.customer_name # => 'John Doe'
113
115
  # invoice.customer_address # => 'Vimmersvej 13'
114
116
  #
117
+ # The delegated methods are public by default.
118
+ # Pass <tt>private: true</tt> to change that.
119
+ #
120
+ # class User < ActiveRecord::Base
121
+ # has_one :profile
122
+ # delegate :first_name, to: :profile
123
+ # delegate :date_of_birth, to: :profile, private: true
124
+ #
125
+ # def age
126
+ # Date.today.year - date_of_birth.year
127
+ # end
128
+ # end
129
+ #
130
+ # User.new.first_name # => "Tomas"
131
+ # User.new.date_of_birth # => NoMethodError: private method `date_of_birth' called for #<User:0x00000008221340>
132
+ # User.new.age # => 2
133
+ #
115
134
  # If the target is +nil+ and does not respond to the delegated method a
116
- # +Module::DelegationError+ is raised, as with any other value. Sometimes,
117
- # however, it makes sense to be robust to that situation and that is the
118
- # purpose of the <tt>:allow_nil</tt> option: If the target is not +nil+, or it
119
- # is and responds to the method, everything works as usual. But if it is +nil+
120
- # and does not respond to the delegated method, +nil+ is returned.
135
+ # +Module::DelegationError+ is raised. If you wish to instead return +nil+,
136
+ # use the <tt>:allow_nil</tt> option.
121
137
  #
122
138
  # class User < ActiveRecord::Base
123
139
  # has_one :profile
@@ -152,9 +168,9 @@ class Module
152
168
  # Foo.new("Bar").name # raises NoMethodError: undefined method `name'
153
169
  #
154
170
  # The target method must be public, otherwise it will raise +NoMethodError+.
155
- def delegate(*methods, to: nil, prefix: nil, allow_nil: nil)
171
+ def delegate(*methods, to: nil, prefix: nil, allow_nil: nil, private: nil)
156
172
  unless to
157
- raise ArgumentError, "Delegation needs a target. Supply an options hash with a :to key as the last argument (e.g. delegate :hello, to: :greeter)."
173
+ raise ArgumentError, "Delegation needs a target. Supply a keyword argument 'to' (e.g. delegate :hello, to: :greeter)."
158
174
  end
159
175
 
160
176
  if prefix == true && /^[^a-z_]/.match?(to)
@@ -174,10 +190,16 @@ class Module
174
190
  to = to.to_s
175
191
  to = "self.#{to}" if DELEGATION_RESERVED_METHOD_NAMES.include?(to)
176
192
 
177
- methods.each do |method|
193
+ method_def = []
194
+ method_names = []
195
+
196
+ methods.map do |method|
197
+ method_name = prefix ? "#{method_prefix}#{method}" : method
198
+ method_names << method_name.to_sym
199
+
178
200
  # Attribute writer methods only accept one argument. Makes sure []=
179
201
  # methods still accept two arguments.
180
- definition = /[^\]]=$/.match?(method) ? "arg" : "*args, &block"
202
+ definition = /[^\]]=\z/.match?(method) ? "arg" : "..."
181
203
 
182
204
  # The following generated method calls the target exactly once, storing
183
205
  # the returned value in a dummy variable.
@@ -187,81 +209,84 @@ class Module
187
209
  # whereas conceptually, from the user point of view, the delegator should
188
210
  # be doing one call.
189
211
  if allow_nil
190
- method_def = [
191
- "def #{method_prefix}#{method}(#{definition})",
192
- "_ = #{to}",
193
- "if !_.nil? || nil.respond_to?(:#{method})",
194
- " _.#{method}(#{definition})",
195
- "end",
196
- "end"
197
- ].join ";"
212
+ method = method.to_s
213
+
214
+ method_def <<
215
+ "def #{method_name}(#{definition})" <<
216
+ " _ = #{to}" <<
217
+ " if !_.nil? || nil.respond_to?(:#{method})" <<
218
+ " _.#{method}(#{definition})" <<
219
+ " end" <<
220
+ "end"
198
221
  else
199
- exception = %(raise DelegationError, "#{self}##{method_prefix}#{method} delegated to #{to}.#{method}, but #{to} is nil: \#{self.inspect}")
222
+ method = method.to_s
223
+ method_name = method_name.to_s
200
224
 
201
- method_def = [
202
- "def #{method_prefix}#{method}(#{definition})",
203
- " _ = #{to}",
204
- " _.#{method}(#{definition})",
205
- "rescue NoMethodError => e",
206
- " if _.nil? && e.name == :#{method}",
207
- " #{exception}",
208
- " else",
209
- " raise",
210
- " end",
225
+ method_def <<
226
+ "def #{method_name}(#{definition})" <<
227
+ " _ = #{to}" <<
228
+ " _.#{method}(#{definition})" <<
229
+ "rescue NoMethodError => e" <<
230
+ " if _.nil? && e.name == :#{method}" <<
231
+ %( raise DelegationError, "#{self}##{method_name} delegated to #{to}.#{method}, but #{to} is nil: \#{self.inspect}") <<
232
+ " else" <<
233
+ " raise" <<
234
+ " end" <<
211
235
  "end"
212
- ].join ";"
213
236
  end
214
-
215
- module_eval(method_def, file, line)
216
237
  end
238
+ module_eval(method_def.join(";"), file, line)
239
+ private(*method_names) if private
240
+ method_names
217
241
  end
218
242
 
219
243
  # When building decorators, a common pattern may emerge:
220
244
  #
221
245
  # class Partition
222
- # def initialize(first_event)
223
- # @events = [ first_event ]
246
+ # def initialize(event)
247
+ # @event = event
224
248
  # end
225
249
  #
226
- # def people
227
- # if @events.first.detail.people.any?
228
- # @events.collect { |e| Array(e.detail.people) }.flatten.uniq
229
- # else
230
- # @events.collect(&:creator).uniq
231
- # end
250
+ # def person
251
+ # detail.person || creator
232
252
  # end
233
253
  #
234
254
  # private
235
255
  # def respond_to_missing?(name, include_private = false)
236
- # @events.respond_to?(name, include_private)
256
+ # @event.respond_to?(name, include_private)
237
257
  # end
238
258
  #
239
259
  # def method_missing(method, *args, &block)
240
- # @events.send(method, *args, &block)
260
+ # @event.send(method, *args, &block)
241
261
  # end
242
262
  # end
243
263
  #
244
- # With `Module#delegate_missing_to`, the above is condensed to:
264
+ # With <tt>Module#delegate_missing_to</tt>, the above is condensed to:
245
265
  #
246
266
  # class Partition
247
- # delegate_missing_to :@events
267
+ # delegate_missing_to :@event
248
268
  #
249
- # def initialize(first_event)
250
- # @events = [ first_event ]
269
+ # def initialize(event)
270
+ # @event = event
251
271
  # end
252
272
  #
253
- # def people
254
- # if @events.first.detail.people.any?
255
- # @events.collect { |e| Array(e.detail.people) }.flatten.uniq
256
- # else
257
- # @events.collect(&:creator).uniq
258
- # end
273
+ # def person
274
+ # detail.person || creator
259
275
  # end
260
276
  # end
261
277
  #
262
- # The target can be anything callable within the object. E.g. instance
263
- # variables, methods, constants and the likes.
264
- def delegate_missing_to(target)
278
+ # The target can be anything callable within the object, e.g. instance
279
+ # variables, methods, constants, etc.
280
+ #
281
+ # The delegated method must be public on the target, otherwise it will
282
+ # raise +DelegationError+. If you wish to instead return +nil+,
283
+ # use the <tt>:allow_nil</tt> option.
284
+ #
285
+ # The <tt>marshal_dump</tt> and <tt>_dump</tt> methods are exempt from
286
+ # delegation due to possible interference when calling
287
+ # <tt>Marshal.dump(object)</tt>, should the delegation target method
288
+ # of <tt>object</tt> add or remove instance variables.
289
+ def delegate_missing_to(target, allow_nil: nil)
265
290
  target = target.to_s
266
291
  target = "self.#{target}" if DELEGATION_RESERVED_METHOD_NAMES.include?(target)
267
292
 
@@ -270,6 +295,7 @@ class Module
270
295
  # It may look like an oversight, but we deliberately do not pass
271
296
  # +include_private+, because they do not get delegated.
272
297
 
298
+ return false if name == :marshal_dump || name == :_dump
273
299
  #{target}.respond_to?(name) || super
274
300
  end
275
301
 
@@ -277,9 +303,22 @@ class Module
277
303
  if #{target}.respond_to?(method)
278
304
  #{target}.public_send(method, *args, &block)
279
305
  else
280
- super
306
+ begin
307
+ super
308
+ rescue NoMethodError
309
+ if #{target}.nil?
310
+ if #{allow_nil == true}
311
+ nil
312
+ else
313
+ raise DelegationError, "\#{method} delegated to #{target}, but #{target} is nil"
314
+ end
315
+ else
316
+ raise
317
+ end
318
+ end
281
319
  end
282
320
  end
321
+ ruby2_keywords(:method_missing)
283
322
  RUBY
284
323
  end
285
324
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Module
2
4
  # deprecate :foo
3
5
  # deprecate bar: 'message'
@@ -1,14 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/string/filters"
1
4
  require "active_support/inflector"
2
5
 
3
6
  class Module
4
7
  # Returns the name of the module containing this one.
5
8
  #
6
- # M::N.parent_name # => "M"
7
- def parent_name
9
+ # M::N.module_parent_name # => "M"
10
+ def module_parent_name
8
11
  if defined?(@parent_name)
9
12
  @parent_name
10
13
  else
11
- parent_name = name =~ /::[^:]+\Z/ ? $`.freeze : nil
14
+ parent_name = name =~ /::[^:]+\z/ ? -$` : nil
12
15
  @parent_name = parent_name unless frozen?
13
16
  parent_name
14
17
  end
@@ -22,15 +25,15 @@ class Module
22
25
  # end
23
26
  # X = M::N
24
27
  #
25
- # M::N.parent # => M
26
- # X.parent # => M
28
+ # M::N.module_parent # => M
29
+ # X.module_parent # => M
27
30
  #
28
31
  # The parent of top-level and anonymous modules is Object.
29
32
  #
30
- # M.parent # => Object
31
- # Module.new.parent # => Object
32
- def parent
33
- parent_name ? ActiveSupport::Inflector.constantize(parent_name) : Object
33
+ # M.module_parent # => Object
34
+ # Module.new.module_parent # => Object
35
+ def module_parent
36
+ module_parent_name ? ActiveSupport::Inflector.constantize(module_parent_name) : Object
34
37
  end
35
38
 
36
39
  # Returns all the parents of this module according to its name, ordered from
@@ -42,13 +45,13 @@ class Module
42
45
  # end
43
46
  # X = M::N
44
47
  #
45
- # M.parents # => [Object]
46
- # M::N.parents # => [M, Object]
47
- # X.parents # => [M, Object]
48
- def parents
48
+ # M.module_parents # => [Object]
49
+ # M::N.module_parents # => [M, Object]
50
+ # X.module_parents # => [M, Object]
51
+ def module_parents
49
52
  parents = []
50
- if parent_name
51
- parts = parent_name.split("::")
53
+ if module_parent_name
54
+ parts = module_parent_name.split("::")
52
55
  until parts.empty?
53
56
  parents << ActiveSupport::Inflector.constantize(parts * "::")
54
57
  parts.pop
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Module
4
+ # Marks the named method as intended to be redefined, if it exists.
5
+ # Suppresses the Ruby method redefinition warning. Prefer
6
+ # #redefine_method where possible.
7
+ def silence_redefinition_of_method(method)
8
+ if method_defined?(method) || private_method_defined?(method)
9
+ # This suppresses the "method redefined" warning; the self-alias
10
+ # looks odd, but means we don't need to generate a unique name
11
+ alias_method method, method
12
+ end
13
+ end
14
+
15
+ # Replaces the existing method definition, if there is one, with the passed
16
+ # block as its body.
17
+ def redefine_method(method, &block)
18
+ visibility = method_visibility(method)
19
+ silence_redefinition_of_method(method)
20
+ define_method(method, &block)
21
+ send(visibility, method)
22
+ end
23
+
24
+ # Replaces the existing singleton method definition, if there is one, with
25
+ # the passed block as its body.
26
+ def redefine_singleton_method(method, &block)
27
+ singleton_class.redefine_method(method, &block)
28
+ end
29
+
30
+ def method_visibility(method) # :nodoc:
31
+ case
32
+ when private_method_defined?(method)
33
+ :private
34
+ when protected_method_defined?(method)
35
+ :protected
36
+ else
37
+ :public
38
+ end
39
+ end
40
+ end
@@ -1,3 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/module/redefine_method"
4
+
1
5
  class Module
2
6
  # Removes the named method, if it exists.
3
7
  def remove_possible_method(method)
@@ -8,28 +12,6 @@ class Module
8
12
 
9
13
  # Removes the named singleton method, if it exists.
10
14
  def remove_possible_singleton_method(method)
11
- singleton_class.instance_eval do
12
- remove_possible_method(method)
13
- end
14
- end
15
-
16
- # Replaces the existing method definition, if there is one, with the passed
17
- # block as its body.
18
- def redefine_method(method, &block)
19
- visibility = method_visibility(method)
20
- remove_possible_method(method)
21
- define_method(method, &block)
22
- send(visibility, method)
23
- end
24
-
25
- def method_visibility(method) # :nodoc:
26
- case
27
- when private_method_defined?(method)
28
- :private
29
- when protected_method_defined?(method)
30
- :protected
31
- else
32
- :public
33
- end
15
+ singleton_class.remove_possible_method(method)
34
16
  end
35
17
  end
@@ -1,11 +1,13 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/core_ext/module/aliasing"
2
4
  require "active_support/core_ext/module/introspection"
3
5
  require "active_support/core_ext/module/anonymous"
4
- require "active_support/core_ext/module/reachable"
5
6
  require "active_support/core_ext/module/attribute_accessors"
6
7
  require "active_support/core_ext/module/attribute_accessors_per_thread"
7
8
  require "active_support/core_ext/module/attr_internal"
8
9
  require "active_support/core_ext/module/concerning"
9
10
  require "active_support/core_ext/module/delegation"
10
11
  require "active_support/core_ext/module/deprecation"
12
+ require "active_support/core_ext/module/redefine_method"
11
13
  require "active_support/core_ext/module/remove_method"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class NameError
2
4
  # Extract the name of the missing constant from the exception message.
3
5
  #
@@ -8,8 +10,26 @@ class NameError
8
10
  # end
9
11
  # # => "HelloWorld"
10
12
  def missing_name
11
- if /undefined local variable or method/ !~ message
12
- $1 if /((::)?([A-Z]\w*)(::[A-Z]\w*)*)$/ =~ message
13
+ # Since ruby v2.3.0 `did_you_mean` gem is loaded by default.
14
+ # It extends NameError#message with spell corrections which are SLOW.
15
+ # We should use original_message message instead.
16
+ message = respond_to?(:original_message) ? original_message : self.message
17
+ return unless message.start_with?("uninitialized constant ")
18
+
19
+ receiver = begin
20
+ self.receiver
21
+ rescue ArgumentError
22
+ nil
23
+ end
24
+
25
+ if receiver == Object
26
+ name.to_s
27
+ elsif receiver
28
+ "#{real_mod_name(receiver)}::#{self.name}"
29
+ else
30
+ if match = message.match(/((::)?([A-Z]\w*)(::[A-Z]\w*)*)$/)
31
+ match[1]
32
+ end
13
33
  end
14
34
  end
15
35
 
@@ -28,4 +48,12 @@ class NameError
28
48
  missing_name == name.to_s
29
49
  end
30
50
  end
51
+
52
+ private
53
+ UNBOUND_METHOD_MODULE_NAME = Module.instance_method(:name)
54
+ private_constant :UNBOUND_METHOD_MODULE_NAME
55
+
56
+ def real_mod_name(mod)
57
+ UNBOUND_METHOD_MODULE_NAME.bind_call(mod)
58
+ end
31
59
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Numeric
2
4
  KILOBYTE = 1024
3
5
  MEGABYTE = KILOBYTE * 1024