activesupport 4.2.11.3 → 5.2.8.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 (256) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +435 -403
  3. data/MIT-LICENSE +2 -2
  4. data/README.rdoc +4 -5
  5. data/lib/active_support/all.rb +5 -3
  6. data/lib/active_support/array_inquirer.rb +48 -0
  7. data/lib/active_support/backtrace_cleaner.rb +7 -5
  8. data/lib/active_support/benchmarkable.rb +6 -4
  9. data/lib/active_support/builder.rb +3 -1
  10. data/lib/active_support/cache/file_store.rb +41 -35
  11. data/lib/active_support/cache/mem_cache_store.rb +91 -91
  12. data/lib/active_support/cache/memory_store.rb +27 -30
  13. data/lib/active_support/cache/null_store.rb +7 -8
  14. data/lib/active_support/cache/redis_cache_store.rb +466 -0
  15. data/lib/active_support/cache/strategy/local_cache.rb +67 -34
  16. data/lib/active_support/cache/strategy/local_cache_middleware.rb +10 -9
  17. data/lib/active_support/cache.rb +287 -196
  18. data/lib/active_support/callbacks.rb +640 -590
  19. data/lib/active_support/concern.rb +11 -5
  20. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +35 -0
  21. data/lib/active_support/concurrency/share_lock.rb +227 -0
  22. data/lib/active_support/configurable.rb +8 -5
  23. data/lib/active_support/core_ext/array/access.rb +29 -1
  24. data/lib/active_support/core_ext/array/conversions.rb +22 -18
  25. data/lib/active_support/core_ext/array/extract_options.rb +2 -0
  26. data/lib/active_support/core_ext/array/grouping.rb +11 -18
  27. data/lib/active_support/core_ext/array/inquiry.rb +19 -0
  28. data/lib/active_support/core_ext/array/prepend_and_append.rb +5 -3
  29. data/lib/active_support/core_ext/array/wrap.rb +7 -4
  30. data/lib/active_support/core_ext/array.rb +9 -6
  31. data/lib/active_support/core_ext/benchmark.rb +3 -1
  32. data/lib/active_support/core_ext/big_decimal/conversions.rb +10 -12
  33. data/lib/active_support/core_ext/big_decimal.rb +3 -1
  34. data/lib/active_support/core_ext/class/attribute.rb +41 -22
  35. data/lib/active_support/core_ext/class/attribute_accessors.rb +3 -1
  36. data/lib/active_support/core_ext/class/subclasses.rb +20 -6
  37. data/lib/active_support/core_ext/class.rb +4 -3
  38. data/lib/active_support/core_ext/date/acts_like.rb +3 -1
  39. data/lib/active_support/core_ext/date/blank.rb +14 -0
  40. data/lib/active_support/core_ext/date/calculations.rb +11 -9
  41. data/lib/active_support/core_ext/date/conversions.rb +25 -23
  42. data/lib/active_support/core_ext/date/zones.rb +4 -2
  43. data/lib/active_support/core_ext/date.rb +6 -4
  44. data/lib/active_support/core_ext/date_and_time/calculations.rb +170 -58
  45. data/lib/active_support/core_ext/date_and_time/compatibility.rb +4 -3
  46. data/lib/active_support/core_ext/date_and_time/zones.rb +12 -12
  47. data/lib/active_support/core_ext/date_time/acts_like.rb +4 -2
  48. data/lib/active_support/core_ext/date_time/blank.rb +14 -0
  49. data/lib/active_support/core_ext/date_time/calculations.rb +36 -18
  50. data/lib/active_support/core_ext/date_time/compatibility.rb +8 -6
  51. data/lib/active_support/core_ext/date_time/conversions.rb +16 -12
  52. data/lib/active_support/core_ext/date_time.rb +7 -5
  53. data/lib/active_support/core_ext/digest/uuid.rb +7 -5
  54. data/lib/active_support/core_ext/digest.rb +3 -0
  55. data/lib/active_support/core_ext/enumerable.rb +101 -33
  56. data/lib/active_support/core_ext/file/atomic.rb +38 -31
  57. data/lib/active_support/core_ext/file.rb +3 -1
  58. data/lib/active_support/core_ext/hash/compact.rb +14 -9
  59. data/lib/active_support/core_ext/hash/conversions.rb +62 -41
  60. data/lib/active_support/core_ext/hash/deep_merge.rb +9 -13
  61. data/lib/active_support/core_ext/hash/except.rb +11 -8
  62. data/lib/active_support/core_ext/hash/indifferent_access.rb +4 -3
  63. data/lib/active_support/core_ext/hash/keys.rb +33 -27
  64. data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
  65. data/lib/active_support/core_ext/hash/slice.rb +8 -8
  66. data/lib/active_support/core_ext/hash/transform_values.rb +14 -5
  67. data/lib/active_support/core_ext/hash.rb +11 -9
  68. data/lib/active_support/core_ext/integer/inflections.rb +3 -1
  69. data/lib/active_support/core_ext/integer/multiple.rb +2 -0
  70. data/lib/active_support/core_ext/integer/time.rb +11 -18
  71. data/lib/active_support/core_ext/integer.rb +5 -3
  72. data/lib/active_support/core_ext/kernel/agnostics.rb +2 -0
  73. data/lib/active_support/core_ext/kernel/concern.rb +5 -1
  74. data/lib/active_support/core_ext/kernel/reporting.rb +4 -84
  75. data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
  76. data/lib/active_support/core_ext/kernel.rb +6 -5
  77. data/lib/active_support/core_ext/load_error.rb +3 -22
  78. data/lib/active_support/core_ext/marshal.rb +8 -8
  79. data/lib/active_support/core_ext/module/aliasing.rb +6 -44
  80. data/lib/active_support/core_ext/module/anonymous.rb +12 -1
  81. data/lib/active_support/core_ext/module/attr_internal.rb +8 -9
  82. data/lib/active_support/core_ext/module/attribute_accessors.rb +43 -40
  83. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +150 -0
  84. data/lib/active_support/core_ext/module/concerning.rb +11 -12
  85. data/lib/active_support/core_ext/module/delegation.rb +98 -36
  86. data/lib/active_support/core_ext/module/deprecation.rb +4 -2
  87. data/lib/active_support/core_ext/module/introspection.rb +9 -9
  88. data/lib/active_support/core_ext/module/reachable.rb +5 -2
  89. data/lib/active_support/core_ext/module/redefine_method.rb +49 -0
  90. data/lib/active_support/core_ext/module/remove_method.rb +8 -3
  91. data/lib/active_support/core_ext/module.rb +14 -11
  92. data/lib/active_support/core_ext/name_error.rb +22 -2
  93. data/lib/active_support/core_ext/numeric/bytes.rb +22 -0
  94. data/lib/active_support/core_ext/numeric/conversions.rb +78 -81
  95. data/lib/active_support/core_ext/numeric/inquiry.rb +28 -0
  96. data/lib/active_support/core_ext/numeric/time.rb +35 -23
  97. data/lib/active_support/core_ext/numeric.rb +6 -3
  98. data/lib/active_support/core_ext/object/acts_like.rb +12 -1
  99. data/lib/active_support/core_ext/object/blank.rb +27 -2
  100. data/lib/active_support/core_ext/object/conversions.rb +6 -4
  101. data/lib/active_support/core_ext/object/deep_dup.rb +13 -4
  102. data/lib/active_support/core_ext/object/duplicable.rb +41 -14
  103. data/lib/active_support/core_ext/object/inclusion.rb +5 -3
  104. data/lib/active_support/core_ext/object/instance_variables.rb +3 -1
  105. data/lib/active_support/core_ext/object/json.rb +49 -19
  106. data/lib/active_support/core_ext/object/to_param.rb +3 -1
  107. data/lib/active_support/core_ext/object/to_query.rb +10 -5
  108. data/lib/active_support/core_ext/object/try.rb +69 -21
  109. data/lib/active_support/core_ext/object/with_options.rb +16 -3
  110. data/lib/active_support/core_ext/object.rb +14 -13
  111. data/lib/active_support/core_ext/range/compare_range.rb +61 -0
  112. data/lib/active_support/core_ext/range/conversions.rb +27 -7
  113. data/lib/active_support/core_ext/range/each.rb +19 -17
  114. data/lib/active_support/core_ext/range/include_range.rb +2 -22
  115. data/lib/active_support/core_ext/range/include_time_with_zone.rb +23 -0
  116. data/lib/active_support/core_ext/range/overlaps.rb +2 -0
  117. data/lib/active_support/core_ext/range.rb +7 -4
  118. data/lib/active_support/core_ext/regexp.rb +6 -0
  119. data/lib/active_support/core_ext/securerandom.rb +25 -0
  120. data/lib/active_support/core_ext/string/access.rb +8 -6
  121. data/lib/active_support/core_ext/string/behavior.rb +3 -1
  122. data/lib/active_support/core_ext/string/conversions.rb +7 -4
  123. data/lib/active_support/core_ext/string/exclude.rb +2 -0
  124. data/lib/active_support/core_ext/string/filters.rb +6 -5
  125. data/lib/active_support/core_ext/string/indent.rb +6 -4
  126. data/lib/active_support/core_ext/string/inflections.rb +61 -24
  127. data/lib/active_support/core_ext/string/inquiry.rb +3 -1
  128. data/lib/active_support/core_ext/string/multibyte.rb +15 -7
  129. data/lib/active_support/core_ext/string/output_safety.rb +62 -38
  130. data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -0
  131. data/lib/active_support/core_ext/string/strip.rb +4 -5
  132. data/lib/active_support/core_ext/string/zones.rb +4 -2
  133. data/lib/active_support/core_ext/string.rb +15 -13
  134. data/lib/active_support/core_ext/time/acts_like.rb +3 -1
  135. data/lib/active_support/core_ext/time/calculations.rb +85 -51
  136. data/lib/active_support/core_ext/time/compatibility.rb +4 -2
  137. data/lib/active_support/core_ext/time/conversions.rb +20 -13
  138. data/lib/active_support/core_ext/time/zones.rb +41 -7
  139. data/lib/active_support/core_ext/time.rb +7 -6
  140. data/lib/active_support/core_ext/uri.rb +6 -8
  141. data/lib/active_support/core_ext.rb +3 -1
  142. data/lib/active_support/current_attributes.rb +195 -0
  143. data/lib/active_support/dependencies/autoload.rb +2 -0
  144. data/lib/active_support/dependencies/interlock.rb +57 -0
  145. data/lib/active_support/dependencies.rb +152 -161
  146. data/lib/active_support/deprecation/behaviors.rb +44 -11
  147. data/lib/active_support/deprecation/constant_accessor.rb +52 -0
  148. data/lib/active_support/deprecation/instance_delegator.rb +17 -2
  149. data/lib/active_support/deprecation/method_wrappers.rb +66 -20
  150. data/lib/active_support/deprecation/proxy_wrappers.rb +56 -28
  151. data/lib/active_support/deprecation/reporting.rb +32 -12
  152. data/lib/active_support/deprecation.rb +12 -9
  153. data/lib/active_support/descendants_tracker.rb +2 -0
  154. data/lib/active_support/digest.rb +20 -0
  155. data/lib/active_support/duration/iso8601_parser.rb +125 -0
  156. data/lib/active_support/duration/iso8601_serializer.rb +55 -0
  157. data/lib/active_support/duration.rb +314 -38
  158. data/lib/active_support/encrypted_configuration.rb +49 -0
  159. data/lib/active_support/encrypted_file.rb +99 -0
  160. data/lib/active_support/evented_file_update_checker.rb +205 -0
  161. data/lib/active_support/execution_wrapper.rb +131 -0
  162. data/lib/active_support/executor.rb +8 -0
  163. data/lib/active_support/file_update_checker.rb +63 -37
  164. data/lib/active_support/gem_version.rb +6 -4
  165. data/lib/active_support/gzip.rb +7 -5
  166. data/lib/active_support/hash_with_indifferent_access.rb +123 -28
  167. data/lib/active_support/i18n.rb +8 -6
  168. data/lib/active_support/i18n_railtie.rb +37 -13
  169. data/lib/active_support/inflections.rb +13 -11
  170. data/lib/active_support/inflector/inflections.rb +61 -12
  171. data/lib/active_support/inflector/methods.rb +163 -136
  172. data/lib/active_support/inflector/transliterate.rb +48 -27
  173. data/lib/active_support/inflector.rb +7 -5
  174. data/lib/active_support/json/decoding.rb +16 -13
  175. data/lib/active_support/json/encoding.rb +11 -58
  176. data/lib/active_support/json.rb +4 -2
  177. data/lib/active_support/key_generator.rb +25 -25
  178. data/lib/active_support/lazy_load_hooks.rb +50 -20
  179. data/lib/active_support/locale/en.yml +2 -0
  180. data/lib/active_support/log_subscriber/test_helper.rb +14 -12
  181. data/lib/active_support/log_subscriber.rb +13 -10
  182. data/lib/active_support/logger.rb +8 -7
  183. data/lib/active_support/logger_silence.rb +6 -4
  184. data/lib/active_support/logger_thread_safe_level.rb +7 -5
  185. data/lib/active_support/message_encryptor.rb +168 -53
  186. data/lib/active_support/message_verifier.rb +150 -17
  187. data/lib/active_support/messages/metadata.rb +71 -0
  188. data/lib/active_support/messages/rotation_configuration.rb +22 -0
  189. data/lib/active_support/messages/rotator.rb +56 -0
  190. data/lib/active_support/multibyte/chars.rb +36 -23
  191. data/lib/active_support/multibyte/unicode.rb +100 -96
  192. data/lib/active_support/multibyte.rb +4 -2
  193. data/lib/active_support/notifications/fanout.rb +11 -9
  194. data/lib/active_support/notifications/instrumenter.rb +27 -7
  195. data/lib/active_support/notifications.rb +11 -7
  196. data/lib/active_support/number_helper/number_converter.rb +13 -11
  197. data/lib/active_support/number_helper/number_to_currency_converter.rb +9 -9
  198. data/lib/active_support/number_helper/number_to_delimited_converter.rb +9 -3
  199. data/lib/active_support/number_helper/number_to_human_converter.rb +11 -9
  200. data/lib/active_support/number_helper/number_to_human_size_converter.rb +9 -8
  201. data/lib/active_support/number_helper/number_to_percentage_converter.rb +3 -1
  202. data/lib/active_support/number_helper/number_to_phone_converter.rb +13 -4
  203. data/lib/active_support/number_helper/number_to_rounded_converter.rb +23 -56
  204. data/lib/active_support/number_helper/rounding_helper.rb +66 -0
  205. data/lib/active_support/number_helper.rb +94 -68
  206. data/lib/active_support/option_merger.rb +3 -1
  207. data/lib/active_support/ordered_hash.rb +6 -4
  208. data/lib/active_support/ordered_options.rb +23 -5
  209. data/lib/active_support/per_thread_registry.rb +9 -4
  210. data/lib/active_support/proxy_object.rb +2 -0
  211. data/lib/active_support/rails.rb +16 -8
  212. data/lib/active_support/railtie.rb +43 -9
  213. data/lib/active_support/reloader.rb +131 -0
  214. data/lib/active_support/rescuable.rb +108 -53
  215. data/lib/active_support/security_utils.rb +15 -11
  216. data/lib/active_support/string_inquirer.rb +11 -3
  217. data/lib/active_support/subscriber.rb +21 -16
  218. data/lib/active_support/tagged_logging.rb +14 -11
  219. data/lib/active_support/test_case.rb +19 -47
  220. data/lib/active_support/testing/assertions.rb +137 -20
  221. data/lib/active_support/testing/autorun.rb +4 -2
  222. data/lib/active_support/testing/constant_lookup.rb +2 -1
  223. data/lib/active_support/testing/declarative.rb +3 -1
  224. data/lib/active_support/testing/deprecation.rb +14 -10
  225. data/lib/active_support/testing/file_fixtures.rb +36 -0
  226. data/lib/active_support/testing/isolation.rb +34 -25
  227. data/lib/active_support/testing/method_call_assertions.rb +43 -0
  228. data/lib/active_support/testing/setup_and_teardown.rb +13 -8
  229. data/lib/active_support/testing/stream.rb +44 -0
  230. data/lib/active_support/testing/tagged_logging.rb +3 -1
  231. data/lib/active_support/testing/time_helpers.rb +81 -15
  232. data/lib/active_support/time.rb +14 -12
  233. data/lib/active_support/time_with_zone.rb +169 -39
  234. data/lib/active_support/values/time_zone.rb +196 -61
  235. data/lib/active_support/values/unicode_tables.dat +0 -0
  236. data/lib/active_support/version.rb +3 -1
  237. data/lib/active_support/xml_mini/jdom.rb +116 -114
  238. data/lib/active_support/xml_mini/libxml.rb +16 -13
  239. data/lib/active_support/xml_mini/libxmlsax.rb +15 -14
  240. data/lib/active_support/xml_mini/nokogiri.rb +14 -12
  241. data/lib/active_support/xml_mini/nokogirisax.rb +14 -13
  242. data/lib/active_support/xml_mini/rexml.rb +11 -9
  243. data/lib/active_support/xml_mini.rb +37 -37
  244. data/lib/active_support.rb +12 -11
  245. metadata +57 -27
  246. data/lib/active_support/concurrency/latch.rb +0 -27
  247. data/lib/active_support/core_ext/big_decimal/yaml_conversions.rb +0 -16
  248. data/lib/active_support/core_ext/class/delegating_attributes.rb +0 -45
  249. data/lib/active_support/core_ext/date_time/zones.rb +0 -6
  250. data/lib/active_support/core_ext/kernel/debugger.rb +0 -10
  251. data/lib/active_support/core_ext/module/method_transplanting.rb +0 -13
  252. data/lib/active_support/core_ext/module/qualified_const.rb +0 -52
  253. data/lib/active_support/core_ext/object/itself.rb +0 -15
  254. data/lib/active_support/core_ext/struct.rb +0 -6
  255. data/lib/active_support/core_ext/thread.rb +0 -86
  256. data/lib/active_support/core_ext/time/marshal.rb +0 -30
@@ -1,6 +1,8 @@
1
- require 'active_support/time_with_zone'
2
- require 'active_support/core_ext/time/acts_like'
3
- require 'active_support/core_ext/date_and_time/zones'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/time_with_zone"
4
+ require "active_support/core_ext/time/acts_like"
5
+ require "active_support/core_ext/date_and_time/zones"
4
6
 
5
7
  class Time
6
8
  include DateAndTime::Zones
@@ -26,7 +28,7 @@ class Time
26
28
  # <tt>current_user.time_zone</tt> just needs to return a string identifying the user's preferred time zone:
27
29
  #
28
30
  # class ApplicationController < ActionController::Base
29
- # around_filter :set_time_zone
31
+ # around_action :set_time_zone
30
32
  #
31
33
  # def set_time_zone
32
34
  # if logged_in?
@@ -40,7 +42,23 @@ class Time
40
42
  Thread.current[:time_zone] = find_zone!(time_zone)
41
43
  end
42
44
 
43
- # Allows override of <tt>Time.zone</tt> locally inside supplied block; resets <tt>Time.zone</tt> to existing value when done.
45
+ # Allows override of <tt>Time.zone</tt> locally inside supplied block;
46
+ # resets <tt>Time.zone</tt> to existing value when done.
47
+ #
48
+ # class ApplicationController < ActionController::Base
49
+ # around_action :set_time_zone
50
+ #
51
+ # private
52
+ #
53
+ # def set_time_zone
54
+ # Time.use_zone(current_user.timezone) { yield }
55
+ # end
56
+ # end
57
+ #
58
+ # NOTE: This won't affect any <tt>ActiveSupport::TimeWithZone</tt>
59
+ # objects that have already been created, e.g. any model timestamp
60
+ # attributes that have been read before the block will remain in
61
+ # the application's default timezone.
44
62
  def use_zone(time_zone)
45
63
  new_zone = find_zone!(time_zone)
46
64
  begin
@@ -51,12 +69,22 @@ class Time
51
69
  end
52
70
  end
53
71
 
54
- # Returns a TimeZone instance or nil, or raises an ArgumentError for invalid timezones.
72
+ # Returns a TimeZone instance matching the time zone provided.
73
+ # Accepts the time zone in any format supported by <tt>Time.zone=</tt>.
74
+ # Raises an +ArgumentError+ for invalid time zones.
75
+ #
76
+ # Time.find_zone! "America/New_York" # => #<ActiveSupport::TimeZone @name="America/New_York" ...>
77
+ # Time.find_zone! "EST" # => #<ActiveSupport::TimeZone @name="EST" ...>
78
+ # Time.find_zone! -5.hours # => #<ActiveSupport::TimeZone @name="Bogota" ...>
79
+ # Time.find_zone! nil # => nil
80
+ # Time.find_zone! false # => false
81
+ # Time.find_zone! "NOT-A-TIMEZONE" # => ArgumentError: Invalid Timezone: NOT-A-TIMEZONE
55
82
  def find_zone!(time_zone)
56
83
  if !time_zone || time_zone.is_a?(ActiveSupport::TimeZone)
57
84
  time_zone
58
85
  else
59
- # lookup timezone based on identifier (unless we've been passed a TZInfo::Timezone)
86
+ # Look up the timezone based on the identifier (unless we've been
87
+ # passed a TZInfo::Timezone)
60
88
  unless time_zone.respond_to?(:period_for_local)
61
89
  time_zone = ActiveSupport::TimeZone[time_zone] || TZInfo::Timezone.get(time_zone)
62
90
  end
@@ -72,6 +100,12 @@ class Time
72
100
  raise ArgumentError, "Invalid Timezone: #{time_zone}"
73
101
  end
74
102
 
103
+ # Returns a TimeZone instance matching the time zone provided.
104
+ # Accepts the time zone in any format supported by <tt>Time.zone=</tt>.
105
+ # Returns +nil+ for invalid time zones.
106
+ #
107
+ # Time.find_zone "America/New_York" # => #<ActiveSupport::TimeZone @name="America/New_York" ...>
108
+ # Time.find_zone "NOT-A-TIMEZONE" # => nil
75
109
  def find_zone(time_zone)
76
110
  find_zone!(time_zone) rescue nil
77
111
  end
@@ -1,6 +1,7 @@
1
- require 'active_support/core_ext/time/acts_like'
2
- require 'active_support/core_ext/time/calculations'
3
- require 'active_support/core_ext/time/compatibility'
4
- require 'active_support/core_ext/time/conversions'
5
- require 'active_support/core_ext/time/marshal'
6
- require 'active_support/core_ext/time/zones'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/time/acts_like"
4
+ require "active_support/core_ext/time/calculations"
5
+ require "active_support/core_ext/time/compatibility"
6
+ require "active_support/core_ext/time/conversions"
7
+ require "active_support/core_ext/time/zones"
@@ -1,18 +1,16 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
- require 'uri'
4
- str = "\xE6\x97\xA5\xE6\x9C\xAC\xE8\xAA\x9E" # Ni-ho-nn-go in UTF-8, means Japanese.
5
- parser = URI::Parser.new
6
-
7
- unless str == parser.unescape(parser.escape(str))
3
+ require "uri"
4
+ if RUBY_VERSION < "2.6.0"
5
+ require "active_support/core_ext/module/redefine_method"
8
6
  URI::Parser.class_eval do
9
- remove_method :unescape
7
+ silence_redefinition_of_method :unescape
10
8
  def unescape(str, escaped = /%[a-fA-F\d]{2}/)
11
9
  # TODO: Are we actually sure that ASCII == UTF-8?
12
10
  # YK: My initial experiments say yes, but let's be sure please
13
11
  enc = str.encoding
14
12
  enc = Encoding::UTF_8 if enc == Encoding::US_ASCII
15
- str.gsub(escaped) { [$&[1, 2].hex].pack('C') }.force_encoding(enc)
13
+ str.dup.force_encoding(Encoding::ASCII_8BIT).gsub(escaped) { |match| [match[1, 2].hex].pack("C") }.force_encoding(enc)
16
14
  end
17
15
  end
18
16
  end
@@ -1,3 +1,5 @@
1
- Dir["#{File.dirname(__FILE__)}/core_ext/*.rb"].each do |path|
1
+ # frozen_string_literal: true
2
+
3
+ Dir.glob(File.expand_path("core_ext/*.rb", __dir__)).each do |path|
2
4
  require path
3
5
  end
@@ -0,0 +1,195 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveSupport
4
+ # Abstract super class that provides a thread-isolated attributes singleton, which resets automatically
5
+ # before and after each request. This allows you to keep all the per-request attributes easily
6
+ # available to the whole system.
7
+ #
8
+ # The following full app-like example demonstrates how to use a Current class to
9
+ # facilitate easy access to the global, per-request attributes without passing them deeply
10
+ # around everywhere:
11
+ #
12
+ # # app/models/current.rb
13
+ # class Current < ActiveSupport::CurrentAttributes
14
+ # attribute :account, :user
15
+ # attribute :request_id, :user_agent, :ip_address
16
+ #
17
+ # resets { Time.zone = nil }
18
+ #
19
+ # def user=(user)
20
+ # super
21
+ # self.account = user.account
22
+ # Time.zone = user.time_zone
23
+ # end
24
+ # end
25
+ #
26
+ # # app/controllers/concerns/authentication.rb
27
+ # module Authentication
28
+ # extend ActiveSupport::Concern
29
+ #
30
+ # included do
31
+ # before_action :authenticate
32
+ # end
33
+ #
34
+ # private
35
+ # def authenticate
36
+ # if authenticated_user = User.find_by(id: cookies.encrypted[:user_id])
37
+ # Current.user = authenticated_user
38
+ # else
39
+ # redirect_to new_session_url
40
+ # end
41
+ # end
42
+ # end
43
+ #
44
+ # # app/controllers/concerns/set_current_request_details.rb
45
+ # module SetCurrentRequestDetails
46
+ # extend ActiveSupport::Concern
47
+ #
48
+ # included do
49
+ # before_action do
50
+ # Current.request_id = request.uuid
51
+ # Current.user_agent = request.user_agent
52
+ # Current.ip_address = request.ip
53
+ # end
54
+ # end
55
+ # end
56
+ #
57
+ # class ApplicationController < ActionController::Base
58
+ # include Authentication
59
+ # include SetCurrentRequestDetails
60
+ # end
61
+ #
62
+ # class MessagesController < ApplicationController
63
+ # def create
64
+ # Current.account.messages.create(message_params)
65
+ # end
66
+ # end
67
+ #
68
+ # class Message < ApplicationRecord
69
+ # belongs_to :creator, default: -> { Current.user }
70
+ # after_create { |message| Event.create(record: message) }
71
+ # end
72
+ #
73
+ # class Event < ApplicationRecord
74
+ # before_create do
75
+ # self.request_id = Current.request_id
76
+ # self.user_agent = Current.user_agent
77
+ # self.ip_address = Current.ip_address
78
+ # end
79
+ # end
80
+ #
81
+ # A word of caution: It's easy to overdo a global singleton like Current and tangle your model as a result.
82
+ # Current should only be used for a few, top-level globals, like account, user, and request details.
83
+ # The attributes stuck in Current should be used by more or less all actions on all requests. If you start
84
+ # sticking controller-specific attributes in there, you're going to create a mess.
85
+ class CurrentAttributes
86
+ include ActiveSupport::Callbacks
87
+ define_callbacks :reset
88
+
89
+ class << self
90
+ # Returns singleton instance for this class in this thread. If none exists, one is created.
91
+ def instance
92
+ current_instances[name] ||= new
93
+ end
94
+
95
+ # Declares one or more attributes that will be given both class and instance accessor methods.
96
+ def attribute(*names)
97
+ generated_attribute_methods.module_eval do
98
+ names.each do |name|
99
+ define_method(name) do
100
+ attributes[name.to_sym]
101
+ end
102
+
103
+ define_method("#{name}=") do |attribute|
104
+ attributes[name.to_sym] = attribute
105
+ end
106
+ end
107
+ end
108
+
109
+ names.each do |name|
110
+ define_singleton_method(name) do
111
+ instance.public_send(name)
112
+ end
113
+
114
+ define_singleton_method("#{name}=") do |attribute|
115
+ instance.public_send("#{name}=", attribute)
116
+ end
117
+ end
118
+ end
119
+
120
+ # Calls this block after #reset is called on the instance. Used for resetting external collaborators, like Time.zone.
121
+ def resets(&block)
122
+ set_callback :reset, :after, &block
123
+ end
124
+
125
+ delegate :set, :reset, to: :instance
126
+
127
+ def reset_all # :nodoc:
128
+ current_instances.each_value(&:reset)
129
+ end
130
+
131
+ def clear_all # :nodoc:
132
+ reset_all
133
+ current_instances.clear
134
+ end
135
+
136
+ private
137
+ def generated_attribute_methods
138
+ @generated_attribute_methods ||= Module.new.tap { |mod| include mod }
139
+ end
140
+
141
+ def current_instances
142
+ Thread.current[:current_attributes_instances] ||= {}
143
+ end
144
+
145
+ def method_missing(name, *args, &block)
146
+ # Caches the method definition as a singleton method of the receiver.
147
+ #
148
+ # By letting #delegate handle it, we avoid an enclosure that'll capture args.
149
+ singleton_class.delegate name, to: :instance
150
+
151
+ send(name, *args, &block)
152
+ end
153
+ end
154
+
155
+ attr_accessor :attributes
156
+
157
+ def initialize
158
+ @attributes = {}
159
+ end
160
+
161
+ # Expose one or more attributes within a block. Old values are returned after the block concludes.
162
+ # Example demonstrating the common use of needing to set Current attributes outside the request-cycle:
163
+ #
164
+ # class Chat::PublicationJob < ApplicationJob
165
+ # def perform(attributes, room_number, creator)
166
+ # Current.set(person: creator) do
167
+ # Chat::Publisher.publish(attributes: attributes, room_number: room_number)
168
+ # end
169
+ # end
170
+ # end
171
+ def set(set_attributes)
172
+ old_attributes = compute_attributes(set_attributes.keys)
173
+ assign_attributes(set_attributes)
174
+ yield
175
+ ensure
176
+ assign_attributes(old_attributes)
177
+ end
178
+
179
+ # Reset all attributes. Should be called before and after actions, when used as a per-request singleton.
180
+ def reset
181
+ run_callbacks :reset do
182
+ self.attributes = {}
183
+ end
184
+ end
185
+
186
+ private
187
+ def assign_attributes(new_attributes)
188
+ new_attributes.each { |key, value| public_send("#{key}=", value) }
189
+ end
190
+
191
+ def compute_attributes(keys)
192
+ keys.collect { |key| [ key, public_send(key) ] }.to_h
193
+ end
194
+ end
195
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/inflector/methods"
2
4
 
3
5
  module ActiveSupport
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/concurrency/share_lock"
4
+
5
+ module ActiveSupport #:nodoc:
6
+ module Dependencies #:nodoc:
7
+ class Interlock
8
+ def initialize # :nodoc:
9
+ @lock = ActiveSupport::Concurrency::ShareLock.new
10
+ end
11
+
12
+ def loading
13
+ @lock.exclusive(purpose: :load, compatible: [:load], after_compatible: [:load]) do
14
+ yield
15
+ end
16
+ end
17
+
18
+ def unloading
19
+ @lock.exclusive(purpose: :unload, compatible: [:load, :unload], after_compatible: [:load, :unload]) do
20
+ yield
21
+ end
22
+ end
23
+
24
+ def start_unloading
25
+ @lock.start_exclusive(purpose: :unload, compatible: [:load, :unload])
26
+ end
27
+
28
+ def done_unloading
29
+ @lock.stop_exclusive(compatible: [:load, :unload])
30
+ end
31
+
32
+ def start_running
33
+ @lock.start_sharing
34
+ end
35
+
36
+ def done_running
37
+ @lock.stop_sharing
38
+ end
39
+
40
+ def running
41
+ @lock.sharing do
42
+ yield
43
+ end
44
+ end
45
+
46
+ def permit_concurrent_loads
47
+ @lock.yield_shares(compatible: [:load]) do
48
+ yield
49
+ end
50
+ end
51
+
52
+ def raw_state(&block) # :nodoc:
53
+ @lock.raw_state(&block)
54
+ end
55
+ end
56
+ end
57
+ end