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,25 +1,9 @@
1
- class LoadError
2
- REGEXPS = [
3
- /^no such file to load -- (.+)$/i,
4
- /^Missing \w+ (?:file\s*)?([^\s]+.rb)$/i,
5
- /^Missing API definition file in (.+)$/i,
6
- /^cannot load such file -- (.+)$/i,
7
- ]
8
-
9
- unless method_defined?(:path)
10
- def path
11
- @path ||= begin
12
- REGEXPS.find do |regex|
13
- message =~ regex
14
- end
15
- $1
16
- end
17
- end
18
- end
1
+ # frozen_string_literal: true
19
2
 
3
+ class LoadError
4
+ # Returns true if the given path name (except perhaps for the ".rb"
5
+ # extension) is the missing file which caused the exception to be raised.
20
6
  def is_missing?(location)
21
- location.sub(/\.rb$/, '') == path.sub(/\.rb$/, '')
7
+ location.delete_suffix(".rb") == path.to_s.delete_suffix(".rb")
22
8
  end
23
9
  end
24
-
25
- MissingSourceFile = LoadError
@@ -1,49 +1,8 @@
1
- class Module
2
- # Encapsulates the common pattern of:
3
- #
4
- # alias_method :foo_without_feature, :foo
5
- # alias_method :foo, :foo_with_feature
6
- #
7
- # With this, you simply do:
8
- #
9
- # alias_method_chain :foo, :feature
10
- #
11
- # And both aliases are set up for you.
12
- #
13
- # Query and bang methods (foo?, foo!) keep the same punctuation:
14
- #
15
- # alias_method_chain :foo?, :feature
16
- #
17
- # is equivalent to
18
- #
19
- # alias_method :foo_without_feature?, :foo?
20
- # alias_method :foo?, :foo_with_feature?
21
- #
22
- # so you can safely chain foo, foo?, and foo! with the same feature.
23
- def alias_method_chain(target, feature)
24
- # Strip out punctuation on predicates or bang methods since
25
- # e.g. target?_without_feature is not a valid method name.
26
- aliased_target, punctuation = target.to_s.sub(/([?!=])$/, ''), $1
27
- yield(aliased_target, punctuation) if block_given?
28
-
29
- with_method = "#{aliased_target}_with_#{feature}#{punctuation}"
30
- without_method = "#{aliased_target}_without_#{feature}#{punctuation}"
31
-
32
- alias_method without_method, target
33
- alias_method target, with_method
34
-
35
- case
36
- when public_method_defined?(without_method)
37
- public target
38
- when protected_method_defined?(without_method)
39
- protected target
40
- when private_method_defined?(without_method)
41
- private target
42
- end
43
- end
1
+ # frozen_string_literal: true
44
2
 
3
+ class Module
45
4
  # Allows you to make aliases for attributes, which includes
46
- # getter, setter, and query methods.
5
+ # getter, setter, and a predicate.
47
6
  #
48
7
  # class Content < ActiveRecord::Base
49
8
  # # has a title attribute
@@ -60,6 +19,9 @@ class Module
60
19
  # e.subject = "Megastars"
61
20
  # e.title # => "Megastars"
62
21
  def alias_attribute(new_name, old_name)
22
+ # The following reader methods use an explicit `self` receiver in order to
23
+ # support aliases that start with an uppercase letter. Otherwise, they would
24
+ # be resolved as constants instead.
63
25
  module_eval <<-STR, __FILE__, __LINE__ + 1
64
26
  def #{new_name}; self.#{old_name}; end # def subject; self.title; end
65
27
  def #{new_name}?; self.#{old_name}?; end # def subject?; self.title?; end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Module
2
4
  # A module may or may not have a name.
3
5
  #
@@ -7,12 +9,21 @@ class Module
7
9
  # m = Module.new
8
10
  # m.name # => nil
9
11
  #
12
+ # +anonymous?+ method returns true if module does not have a name, false otherwise:
13
+ #
14
+ # Module.new.anonymous? # => true
15
+ #
16
+ # module M; end
17
+ # M.anonymous? # => false
18
+ #
10
19
  # A module gets a name when it is first assigned to a constant. Either
11
20
  # via the +module+ or +class+ keyword or by an explicit assignment:
12
21
  #
13
22
  # m = Module.new # creates an anonymous module
14
- # M = m # => m gets a name here as a side-effect
23
+ # m.anonymous? # => true
24
+ # M = m # m gets a name here as a side-effect
15
25
  # m.name # => "M"
26
+ # m.anonymous? # => false
16
27
  def anonymous?
17
28
  name.nil?
18
29
  end
@@ -1,12 +1,14 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Module
2
4
  # Declares an attribute reader backed by an internally-named instance variable.
3
5
  def attr_internal_reader(*attrs)
4
- attrs.each {|attr_name| attr_internal_define(attr_name, :reader)}
6
+ attrs.each { |attr_name| attr_internal_define(attr_name, :reader) }
5
7
  end
6
8
 
7
9
  # Declares an attribute writer backed by an internally-named instance variable.
8
10
  def attr_internal_writer(*attrs)
9
- attrs.each {|attr_name| attr_internal_define(attr_name, :writer)}
11
+ attrs.each { |attr_name| attr_internal_define(attr_name, :writer) }
10
12
  end
11
13
 
12
14
  # Declares an attribute reader and writer backed by an internally-named instance
@@ -18,7 +20,7 @@ class Module
18
20
  alias_method :attr_internal, :attr_internal_accessor
19
21
 
20
22
  class << self; attr_accessor :attr_internal_naming_format end
21
- self.attr_internal_naming_format = '@_%s'
23
+ self.attr_internal_naming_format = "@_%s"
22
24
 
23
25
  private
24
26
  def attr_internal_ivar_name(attr)
@@ -26,11 +28,9 @@ class Module
26
28
  end
27
29
 
28
30
  def attr_internal_define(attr_name, type)
29
- internal_name = attr_internal_ivar_name(attr_name).sub(/\A@/, '')
30
- class_eval do # class_eval is necessary on 1.9 or else the methods a made private
31
- # use native attr_* methods as they are faster on some Ruby implementations
32
- send("attr_#{type}", internal_name)
33
- end
31
+ internal_name = attr_internal_ivar_name(attr_name).delete_prefix("@")
32
+ # use native attr_* methods as they are faster on some Ruby implementations
33
+ public_send("attr_#{type}", internal_name)
34
34
  attr_name, internal_name = "#{attr_name}=", "#{internal_name}=" if type == :writer
35
35
  alias_method attr_name, internal_name
36
36
  remove_method internal_name
@@ -1,66 +1,208 @@
1
- require 'active_support/core_ext/array/extract_options'
1
+ # frozen_string_literal: true
2
2
 
3
+ # == Attribute Accessors
4
+ #
5
+ # Extends the module object with class/module and instance accessors for
6
+ # class/module attributes, just like the native attr* accessors for instance
7
+ # attributes.
3
8
  class Module
4
- def mattr_reader(*syms)
5
- options = syms.extract_options!
9
+ # Defines a class attribute and creates a class and instance reader methods.
10
+ # The underlying class variable is set to +nil+, if it is not previously
11
+ # defined. All class and instance methods created will be public, even if
12
+ # this method is called with a private or protected access modifier.
13
+ #
14
+ # module HairColors
15
+ # mattr_reader :hair_colors
16
+ # end
17
+ #
18
+ # HairColors.hair_colors # => nil
19
+ # HairColors.class_variable_set("@@hair_colors", [:brown, :black])
20
+ # HairColors.hair_colors # => [:brown, :black]
21
+ #
22
+ # The attribute name must be a valid method name in Ruby.
23
+ #
24
+ # module Foo
25
+ # mattr_reader :"1_Badname"
26
+ # end
27
+ # # => NameError: invalid attribute name: 1_Badname
28
+ #
29
+ # To omit the instance reader method, pass
30
+ # <tt>instance_reader: false</tt> or <tt>instance_accessor: false</tt>.
31
+ #
32
+ # module HairColors
33
+ # mattr_reader :hair_colors, instance_reader: false
34
+ # end
35
+ #
36
+ # class Person
37
+ # include HairColors
38
+ # end
39
+ #
40
+ # Person.new.hair_colors # => NoMethodError
41
+ #
42
+ # You can set a default value for the attribute.
43
+ #
44
+ # module HairColors
45
+ # mattr_reader :hair_colors, default: [:brown, :black, :blonde, :red]
46
+ # end
47
+ #
48
+ # class Person
49
+ # include HairColors
50
+ # end
51
+ #
52
+ # Person.new.hair_colors # => [:brown, :black, :blonde, :red]
53
+ def mattr_reader(*syms, instance_reader: true, instance_accessor: true, default: nil, location: nil)
54
+ raise TypeError, "module attributes should be defined directly on class, not singleton" if singleton_class?
55
+ location ||= caller_locations(1, 1).first
56
+
57
+ definition = []
6
58
  syms.each do |sym|
7
- raise NameError.new('invalid attribute name') unless sym =~ /^[_A-Za-z]\w*$/
8
- class_eval(<<-EOS, __FILE__, __LINE__ + 1)
9
- @@#{sym} = nil unless defined? @@#{sym}
59
+ raise NameError.new("invalid attribute name: #{sym}") unless /\A[_A-Za-z]\w*\z/.match?(sym)
10
60
 
11
- def self.#{sym}
12
- @@#{sym}
13
- end
14
- EOS
61
+ definition << "def self.#{sym}; @@#{sym}; end"
15
62
 
16
- unless options[:instance_reader] == false || options[:instance_accessor] == false
17
- class_eval(<<-EOS, __FILE__, __LINE__ + 1)
18
- def #{sym}
19
- @@#{sym}
20
- end
21
- EOS
63
+ if instance_reader && instance_accessor
64
+ definition << "def #{sym}; @@#{sym}; end"
22
65
  end
66
+
67
+ sym_default_value = (block_given? && default.nil?) ? yield : default
68
+ class_variable_set("@@#{sym}", sym_default_value) unless sym_default_value.nil? && class_variable_defined?("@@#{sym}")
23
69
  end
70
+
71
+ module_eval(definition.join(";"), location.path, location.lineno)
24
72
  end
73
+ alias :cattr_reader :mattr_reader
25
74
 
26
- def mattr_writer(*syms)
27
- options = syms.extract_options!
75
+ # Defines a class attribute and creates a class and instance writer methods to
76
+ # allow assignment to the attribute. All class and instance methods created
77
+ # will be public, even if this method is called with a private or protected
78
+ # access modifier.
79
+ #
80
+ # module HairColors
81
+ # mattr_writer :hair_colors
82
+ # end
83
+ #
84
+ # class Person
85
+ # include HairColors
86
+ # end
87
+ #
88
+ # HairColors.hair_colors = [:brown, :black]
89
+ # Person.class_variable_get("@@hair_colors") # => [:brown, :black]
90
+ # Person.new.hair_colors = [:blonde, :red]
91
+ # HairColors.class_variable_get("@@hair_colors") # => [:blonde, :red]
92
+ #
93
+ # To omit the instance writer method, pass
94
+ # <tt>instance_writer: false</tt> or <tt>instance_accessor: false</tt>.
95
+ #
96
+ # module HairColors
97
+ # mattr_writer :hair_colors, instance_writer: false
98
+ # end
99
+ #
100
+ # class Person
101
+ # include HairColors
102
+ # end
103
+ #
104
+ # Person.new.hair_colors = [:blonde, :red] # => NoMethodError
105
+ #
106
+ # You can set a default value for the attribute.
107
+ #
108
+ # module HairColors
109
+ # mattr_writer :hair_colors, default: [:brown, :black, :blonde, :red]
110
+ # end
111
+ #
112
+ # class Person
113
+ # include HairColors
114
+ # end
115
+ #
116
+ # Person.class_variable_get("@@hair_colors") # => [:brown, :black, :blonde, :red]
117
+ def mattr_writer(*syms, instance_writer: true, instance_accessor: true, default: nil, location: nil)
118
+ raise TypeError, "module attributes should be defined directly on class, not singleton" if singleton_class?
119
+ location ||= caller_locations(1, 1).first
120
+
121
+ definition = []
28
122
  syms.each do |sym|
29
- raise NameError.new('invalid attribute name') unless sym =~ /^[_A-Za-z]\w*$/
30
- class_eval(<<-EOS, __FILE__, __LINE__ + 1)
31
- def self.#{sym}=(obj)
32
- @@#{sym} = obj
33
- end
34
- EOS
123
+ raise NameError.new("invalid attribute name: #{sym}") unless /\A[_A-Za-z]\w*\z/.match?(sym)
124
+ definition << "def self.#{sym}=(val); @@#{sym} = val; end"
35
125
 
36
- unless options[:instance_writer] == false || options[:instance_accessor] == false
37
- class_eval(<<-EOS, __FILE__, __LINE__ + 1)
38
- def #{sym}=(obj)
39
- @@#{sym} = obj
40
- end
41
- EOS
126
+ if instance_writer && instance_accessor
127
+ definition << "def #{sym}=(val); @@#{sym} = val; end"
42
128
  end
129
+
130
+ sym_default_value = (block_given? && default.nil?) ? yield : default
131
+ class_variable_set("@@#{sym}", sym_default_value) unless sym_default_value.nil? && class_variable_defined?("@@#{sym}")
43
132
  end
133
+
134
+ module_eval(definition.join(";"), location.path, location.lineno)
44
135
  end
136
+ alias :cattr_writer :mattr_writer
45
137
 
46
- # Extends the module object with module and instance accessors for class attributes,
47
- # just like the native attr* accessors for instance attributes.
138
+ # Defines both class and instance accessors for class attributes.
139
+ # All class and instance methods created will be public, even if
140
+ # this method is called with a private or protected access modifier.
141
+ #
142
+ # module HairColors
143
+ # mattr_accessor :hair_colors
144
+ # end
145
+ #
146
+ # class Person
147
+ # include HairColors
148
+ # end
149
+ #
150
+ # HairColors.hair_colors = [:brown, :black, :blonde, :red]
151
+ # HairColors.hair_colors # => [:brown, :black, :blonde, :red]
152
+ # Person.new.hair_colors # => [:brown, :black, :blonde, :red]
48
153
  #
49
- # module AppConfiguration
50
- # mattr_accessor :google_api_key
154
+ # If a subclass changes the value then that would also change the value for
155
+ # parent class. Similarly if parent class changes the value then that would
156
+ # change the value of subclasses too.
51
157
  #
52
- # self.google_api_key = "123456789"
158
+ # class Citizen < Person
53
159
  # end
54
160
  #
55
- # AppConfiguration.google_api_key # => "123456789"
56
- # AppConfiguration.google_api_key = "overriding the api key!"
57
- # AppConfiguration.google_api_key # => "overriding the api key!"
161
+ # Citizen.new.hair_colors << :blue
162
+ # Person.new.hair_colors # => [:brown, :black, :blonde, :red, :blue]
163
+ #
164
+ # To omit the instance writer method, pass <tt>instance_writer: false</tt>.
165
+ # To omit the instance reader method, pass <tt>instance_reader: false</tt>.
166
+ #
167
+ # module HairColors
168
+ # mattr_accessor :hair_colors, instance_writer: false, instance_reader: false
169
+ # end
170
+ #
171
+ # class Person
172
+ # include HairColors
173
+ # end
174
+ #
175
+ # Person.new.hair_colors = [:brown] # => NoMethodError
176
+ # Person.new.hair_colors # => NoMethodError
177
+ #
178
+ # Or pass <tt>instance_accessor: false</tt>, to omit both instance methods.
179
+ #
180
+ # module HairColors
181
+ # mattr_accessor :hair_colors, instance_accessor: false
182
+ # end
183
+ #
184
+ # class Person
185
+ # include HairColors
186
+ # end
187
+ #
188
+ # Person.new.hair_colors = [:brown] # => NoMethodError
189
+ # Person.new.hair_colors # => NoMethodError
190
+ #
191
+ # You can set a default value for the attribute.
192
+ #
193
+ # module HairColors
194
+ # mattr_accessor :hair_colors, default: [:brown, :black, :blonde, :red]
195
+ # end
196
+ #
197
+ # class Person
198
+ # include HairColors
199
+ # end
58
200
  #
59
- # To opt out of the instance writer method, pass <tt>instance_writer: false</tt>.
60
- # To opt out of the instance reader method, pass <tt>instance_reader: false</tt>.
61
- # To opt out of both instance methods, pass <tt>instance_accessor: false</tt>.
62
- def mattr_accessor(*syms)
63
- mattr_reader(*syms)
64
- mattr_writer(*syms)
201
+ # Person.class_variable_get("@@hair_colors") # => [:brown, :black, :blonde, :red]
202
+ def mattr_accessor(*syms, instance_reader: true, instance_writer: true, instance_accessor: true, default: nil, &blk)
203
+ location = caller_locations(1, 1).first
204
+ mattr_reader(*syms, instance_reader: instance_reader, instance_accessor: instance_accessor, default: default, location: location, &blk)
205
+ mattr_writer(*syms, instance_writer: instance_writer, instance_accessor: instance_accessor, default: default, location: location)
65
206
  end
207
+ alias :cattr_accessor :mattr_accessor
66
208
  end
@@ -0,0 +1,157 @@
1
+ # frozen_string_literal: true
2
+
3
+ # == Attribute Accessors per Thread
4
+ #
5
+ # Extends the module object with class/module and instance accessors for
6
+ # class/module attributes, just like the native attr* accessors for instance
7
+ # attributes, but does so on a per-thread basis.
8
+ #
9
+ # So the values are scoped within the Thread.current space under the class name
10
+ # of the module.
11
+ #
12
+ # Note that it can also be scoped per-fiber if Rails.application.config.active_support.isolation_level
13
+ # is set to `:fiber`
14
+ class Module
15
+ # Defines a per-thread class attribute and creates class and instance reader methods.
16
+ # The underlying per-thread class variable is set to +nil+, if it is not previously defined.
17
+ #
18
+ # module Current
19
+ # thread_mattr_reader :user
20
+ # end
21
+ #
22
+ # Current.user = "DHH"
23
+ # Current.user # => "DHH"
24
+ # Thread.new { Current.user }.values # => nil
25
+ #
26
+ # The attribute name must be a valid method name in Ruby.
27
+ #
28
+ # module Foo
29
+ # thread_mattr_reader :"1_Badname"
30
+ # end
31
+ # # => NameError: invalid attribute name: 1_Badname
32
+ #
33
+ # To omit the instance reader method, pass
34
+ # <tt>instance_reader: false</tt> or <tt>instance_accessor: false</tt>.
35
+ #
36
+ # class Current
37
+ # thread_mattr_reader :user, instance_reader: false
38
+ # end
39
+ #
40
+ # Current.new.user # => NoMethodError
41
+ def thread_mattr_reader(*syms, instance_reader: true, instance_accessor: true, default: nil) # :nodoc:
42
+ syms.each do |sym|
43
+ raise NameError.new("invalid attribute name: #{sym}") unless /^[_A-Za-z]\w*$/.match?(sym)
44
+
45
+ # The following generated method concatenates `name` because we want it
46
+ # to work with inheritance via polymorphism.
47
+ class_eval(<<-EOS, __FILE__, __LINE__ + 1)
48
+ def self.#{sym}
49
+ @__thread_mattr_#{sym} ||= "attr_\#{name}_#{sym}"
50
+ ::ActiveSupport::IsolatedExecutionState[@__thread_mattr_#{sym}]
51
+ end
52
+ EOS
53
+
54
+ if instance_reader && instance_accessor
55
+ class_eval(<<-EOS, __FILE__, __LINE__ + 1)
56
+ def #{sym}
57
+ self.class.#{sym}
58
+ end
59
+ EOS
60
+ end
61
+
62
+ ::ActiveSupport::IsolatedExecutionState["attr_#{name}_#{sym}"] = default unless default.nil?
63
+ end
64
+ end
65
+ alias :thread_cattr_reader :thread_mattr_reader
66
+
67
+ # Defines a per-thread class attribute and creates a class and instance writer methods to
68
+ # allow assignment to the attribute.
69
+ #
70
+ # module Current
71
+ # thread_mattr_writer :user
72
+ # end
73
+ #
74
+ # Current.user = "DHH"
75
+ # Thread.current[:attr_Current_user] # => "DHH"
76
+ #
77
+ # To omit the instance writer method, pass
78
+ # <tt>instance_writer: false</tt> or <tt>instance_accessor: false</tt>.
79
+ #
80
+ # class Current
81
+ # thread_mattr_writer :user, instance_writer: false
82
+ # end
83
+ #
84
+ # Current.new.user = "DHH" # => NoMethodError
85
+ def thread_mattr_writer(*syms, instance_writer: true, instance_accessor: true, default: nil) # :nodoc:
86
+ syms.each do |sym|
87
+ raise NameError.new("invalid attribute name: #{sym}") unless /^[_A-Za-z]\w*$/.match?(sym)
88
+
89
+ # The following generated method concatenates `name` because we want it
90
+ # to work with inheritance via polymorphism.
91
+ class_eval(<<-EOS, __FILE__, __LINE__ + 1)
92
+ def self.#{sym}=(obj)
93
+ @__thread_mattr_#{sym} ||= "attr_\#{name}_#{sym}"
94
+ ::ActiveSupport::IsolatedExecutionState[@__thread_mattr_#{sym}] = obj
95
+ end
96
+ EOS
97
+
98
+ if instance_writer && instance_accessor
99
+ class_eval(<<-EOS, __FILE__, __LINE__ + 1)
100
+ def #{sym}=(obj)
101
+ self.class.#{sym} = obj
102
+ end
103
+ EOS
104
+ end
105
+
106
+ public_send("#{sym}=", default) unless default.nil?
107
+ end
108
+ end
109
+ alias :thread_cattr_writer :thread_mattr_writer
110
+
111
+ # Defines both class and instance accessors for class attributes.
112
+ #
113
+ # class Account
114
+ # thread_mattr_accessor :user
115
+ # end
116
+ #
117
+ # Account.user = "DHH"
118
+ # Account.user # => "DHH"
119
+ # Account.new.user # => "DHH"
120
+ #
121
+ # Unlike `mattr_accessor`, values are *not* shared with subclasses or parent classes.
122
+ # If a subclass changes the value, the parent class' value is not changed.
123
+ # If the parent class changes the value, the value of subclasses is not changed.
124
+ #
125
+ # class Customer < Account
126
+ # end
127
+ #
128
+ # Account.user # => "DHH"
129
+ # Customer.user # => nil
130
+ # Customer.user = "Rafael"
131
+ # Customer.user # => "Rafael"
132
+ # Account.user # => "DHH"
133
+ #
134
+ # To omit the instance writer method, pass <tt>instance_writer: false</tt>.
135
+ # To omit the instance reader method, pass <tt>instance_reader: false</tt>.
136
+ #
137
+ # class Current
138
+ # thread_mattr_accessor :user, instance_writer: false, instance_reader: false
139
+ # end
140
+ #
141
+ # Current.new.user = "DHH" # => NoMethodError
142
+ # Current.new.user # => NoMethodError
143
+ #
144
+ # Or pass <tt>instance_accessor: false</tt>, to omit both instance methods.
145
+ #
146
+ # class Current
147
+ # thread_mattr_accessor :user, instance_accessor: false
148
+ # end
149
+ #
150
+ # Current.new.user = "DHH" # => NoMethodError
151
+ # Current.new.user # => NoMethodError
152
+ def thread_mattr_accessor(*syms, instance_reader: true, instance_writer: true, instance_accessor: true, default: nil)
153
+ thread_mattr_reader(*syms, instance_reader: instance_reader, instance_accessor: instance_accessor, default: default)
154
+ thread_mattr_writer(*syms, instance_writer: instance_writer, instance_accessor: instance_accessor)
155
+ end
156
+ alias :thread_cattr_accessor :thread_mattr_accessor
157
+ end