activesupport 5.0.7.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 (236) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +1013 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.rdoc +39 -0
  5. data/lib/active_support.rb +99 -0
  6. data/lib/active_support/all.rb +3 -0
  7. data/lib/active_support/array_inquirer.rb +44 -0
  8. data/lib/active_support/backtrace_cleaner.rb +103 -0
  9. data/lib/active_support/benchmarkable.rb +49 -0
  10. data/lib/active_support/builder.rb +6 -0
  11. data/lib/active_support/cache.rb +701 -0
  12. data/lib/active_support/cache/file_store.rb +204 -0
  13. data/lib/active_support/cache/mem_cache_store.rb +207 -0
  14. data/lib/active_support/cache/memory_store.rb +167 -0
  15. data/lib/active_support/cache/null_store.rb +41 -0
  16. data/lib/active_support/cache/strategy/local_cache.rb +172 -0
  17. data/lib/active_support/cache/strategy/local_cache_middleware.rb +44 -0
  18. data/lib/active_support/callbacks.rb +791 -0
  19. data/lib/active_support/concern.rb +142 -0
  20. data/lib/active_support/concurrency/latch.rb +26 -0
  21. data/lib/active_support/concurrency/share_lock.rb +226 -0
  22. data/lib/active_support/configurable.rb +148 -0
  23. data/lib/active_support/core_ext.rb +4 -0
  24. data/lib/active_support/core_ext/array.rb +7 -0
  25. data/lib/active_support/core_ext/array/access.rb +90 -0
  26. data/lib/active_support/core_ext/array/conversions.rb +211 -0
  27. data/lib/active_support/core_ext/array/extract_options.rb +29 -0
  28. data/lib/active_support/core_ext/array/grouping.rb +107 -0
  29. data/lib/active_support/core_ext/array/inquiry.rb +17 -0
  30. data/lib/active_support/core_ext/array/prepend_and_append.rb +7 -0
  31. data/lib/active_support/core_ext/array/wrap.rb +46 -0
  32. data/lib/active_support/core_ext/benchmark.rb +14 -0
  33. data/lib/active_support/core_ext/big_decimal.rb +1 -0
  34. data/lib/active_support/core_ext/big_decimal/conversions.rb +14 -0
  35. data/lib/active_support/core_ext/class.rb +2 -0
  36. data/lib/active_support/core_ext/class/attribute.rb +128 -0
  37. data/lib/active_support/core_ext/class/attribute_accessors.rb +4 -0
  38. data/lib/active_support/core_ext/class/subclasses.rb +41 -0
  39. data/lib/active_support/core_ext/date.rb +5 -0
  40. data/lib/active_support/core_ext/date/acts_like.rb +8 -0
  41. data/lib/active_support/core_ext/date/blank.rb +12 -0
  42. data/lib/active_support/core_ext/date/calculations.rb +143 -0
  43. data/lib/active_support/core_ext/date/conversions.rb +95 -0
  44. data/lib/active_support/core_ext/date/zones.rb +6 -0
  45. data/lib/active_support/core_ext/date_and_time/calculations.rb +335 -0
  46. data/lib/active_support/core_ext/date_and_time/compatibility.rb +14 -0
  47. data/lib/active_support/core_ext/date_and_time/zones.rb +40 -0
  48. data/lib/active_support/core_ext/date_time.rb +5 -0
  49. data/lib/active_support/core_ext/date_time/acts_like.rb +14 -0
  50. data/lib/active_support/core_ext/date_time/blank.rb +12 -0
  51. data/lib/active_support/core_ext/date_time/calculations.rb +199 -0
  52. data/lib/active_support/core_ext/date_time/compatibility.rb +16 -0
  53. data/lib/active_support/core_ext/date_time/conversions.rb +105 -0
  54. data/lib/active_support/core_ext/digest/uuid.rb +51 -0
  55. data/lib/active_support/core_ext/enumerable.rb +146 -0
  56. data/lib/active_support/core_ext/file.rb +1 -0
  57. data/lib/active_support/core_ext/file/atomic.rb +68 -0
  58. data/lib/active_support/core_ext/hash.rb +9 -0
  59. data/lib/active_support/core_ext/hash/compact.rb +24 -0
  60. data/lib/active_support/core_ext/hash/conversions.rb +262 -0
  61. data/lib/active_support/core_ext/hash/deep_merge.rb +38 -0
  62. data/lib/active_support/core_ext/hash/except.rb +22 -0
  63. data/lib/active_support/core_ext/hash/indifferent_access.rb +23 -0
  64. data/lib/active_support/core_ext/hash/keys.rb +170 -0
  65. data/lib/active_support/core_ext/hash/reverse_merge.rb +22 -0
  66. data/lib/active_support/core_ext/hash/slice.rb +48 -0
  67. data/lib/active_support/core_ext/hash/transform_values.rb +29 -0
  68. data/lib/active_support/core_ext/integer.rb +3 -0
  69. data/lib/active_support/core_ext/integer/inflections.rb +29 -0
  70. data/lib/active_support/core_ext/integer/multiple.rb +10 -0
  71. data/lib/active_support/core_ext/integer/time.rb +29 -0
  72. data/lib/active_support/core_ext/kernel.rb +4 -0
  73. data/lib/active_support/core_ext/kernel/agnostics.rb +11 -0
  74. data/lib/active_support/core_ext/kernel/concern.rb +12 -0
  75. data/lib/active_support/core_ext/kernel/debugger.rb +3 -0
  76. data/lib/active_support/core_ext/kernel/reporting.rb +43 -0
  77. data/lib/active_support/core_ext/kernel/singleton_class.rb +6 -0
  78. data/lib/active_support/core_ext/load_error.rb +31 -0
  79. data/lib/active_support/core_ext/marshal.rb +22 -0
  80. data/lib/active_support/core_ext/module.rb +12 -0
  81. data/lib/active_support/core_ext/module/aliasing.rb +74 -0
  82. data/lib/active_support/core_ext/module/anonymous.rb +28 -0
  83. data/lib/active_support/core_ext/module/attr_internal.rb +36 -0
  84. data/lib/active_support/core_ext/module/attribute_accessors.rb +212 -0
  85. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +141 -0
  86. data/lib/active_support/core_ext/module/concerning.rb +135 -0
  87. data/lib/active_support/core_ext/module/delegation.rb +216 -0
  88. data/lib/active_support/core_ext/module/deprecation.rb +23 -0
  89. data/lib/active_support/core_ext/module/introspection.rb +68 -0
  90. data/lib/active_support/core_ext/module/method_transplanting.rb +3 -0
  91. data/lib/active_support/core_ext/module/qualified_const.rb +70 -0
  92. data/lib/active_support/core_ext/module/reachable.rb +8 -0
  93. data/lib/active_support/core_ext/module/remove_method.rb +35 -0
  94. data/lib/active_support/core_ext/name_error.rb +31 -0
  95. data/lib/active_support/core_ext/numeric.rb +4 -0
  96. data/lib/active_support/core_ext/numeric/bytes.rb +64 -0
  97. data/lib/active_support/core_ext/numeric/conversions.rb +144 -0
  98. data/lib/active_support/core_ext/numeric/inquiry.rb +26 -0
  99. data/lib/active_support/core_ext/numeric/time.rb +74 -0
  100. data/lib/active_support/core_ext/object.rb +14 -0
  101. data/lib/active_support/core_ext/object/acts_like.rb +10 -0
  102. data/lib/active_support/core_ext/object/blank.rb +143 -0
  103. data/lib/active_support/core_ext/object/conversions.rb +4 -0
  104. data/lib/active_support/core_ext/object/deep_dup.rb +53 -0
  105. data/lib/active_support/core_ext/object/duplicable.rb +124 -0
  106. data/lib/active_support/core_ext/object/inclusion.rb +27 -0
  107. data/lib/active_support/core_ext/object/instance_variables.rb +28 -0
  108. data/lib/active_support/core_ext/object/json.rb +205 -0
  109. data/lib/active_support/core_ext/object/to_param.rb +1 -0
  110. data/lib/active_support/core_ext/object/to_query.rb +84 -0
  111. data/lib/active_support/core_ext/object/try.rb +146 -0
  112. data/lib/active_support/core_ext/object/with_options.rb +69 -0
  113. data/lib/active_support/core_ext/range.rb +4 -0
  114. data/lib/active_support/core_ext/range/conversions.rb +31 -0
  115. data/lib/active_support/core_ext/range/each.rb +21 -0
  116. data/lib/active_support/core_ext/range/include_range.rb +23 -0
  117. data/lib/active_support/core_ext/range/overlaps.rb +8 -0
  118. data/lib/active_support/core_ext/regexp.rb +5 -0
  119. data/lib/active_support/core_ext/securerandom.rb +23 -0
  120. data/lib/active_support/core_ext/string.rb +13 -0
  121. data/lib/active_support/core_ext/string/access.rb +104 -0
  122. data/lib/active_support/core_ext/string/behavior.rb +6 -0
  123. data/lib/active_support/core_ext/string/conversions.rb +57 -0
  124. data/lib/active_support/core_ext/string/exclude.rb +11 -0
  125. data/lib/active_support/core_ext/string/filters.rb +102 -0
  126. data/lib/active_support/core_ext/string/indent.rb +43 -0
  127. data/lib/active_support/core_ext/string/inflections.rb +244 -0
  128. data/lib/active_support/core_ext/string/inquiry.rb +13 -0
  129. data/lib/active_support/core_ext/string/multibyte.rb +53 -0
  130. data/lib/active_support/core_ext/string/output_safety.rb +260 -0
  131. data/lib/active_support/core_ext/string/starts_ends_with.rb +4 -0
  132. data/lib/active_support/core_ext/string/strip.rb +23 -0
  133. data/lib/active_support/core_ext/string/zones.rb +14 -0
  134. data/lib/active_support/core_ext/struct.rb +3 -0
  135. data/lib/active_support/core_ext/time.rb +5 -0
  136. data/lib/active_support/core_ext/time/acts_like.rb +8 -0
  137. data/lib/active_support/core_ext/time/calculations.rb +290 -0
  138. data/lib/active_support/core_ext/time/compatibility.rb +14 -0
  139. data/lib/active_support/core_ext/time/conversions.rb +67 -0
  140. data/lib/active_support/core_ext/time/marshal.rb +3 -0
  141. data/lib/active_support/core_ext/time/zones.rb +111 -0
  142. data/lib/active_support/core_ext/uri.rb +24 -0
  143. data/lib/active_support/dependencies.rb +755 -0
  144. data/lib/active_support/dependencies/autoload.rb +77 -0
  145. data/lib/active_support/dependencies/interlock.rb +55 -0
  146. data/lib/active_support/deprecation.rb +43 -0
  147. data/lib/active_support/deprecation/behaviors.rb +90 -0
  148. data/lib/active_support/deprecation/instance_delegator.rb +37 -0
  149. data/lib/active_support/deprecation/method_wrappers.rb +70 -0
  150. data/lib/active_support/deprecation/proxy_wrappers.rb +149 -0
  151. data/lib/active_support/deprecation/reporting.rb +112 -0
  152. data/lib/active_support/descendants_tracker.rb +60 -0
  153. data/lib/active_support/duration.rb +235 -0
  154. data/lib/active_support/duration/iso8601_parser.rb +122 -0
  155. data/lib/active_support/duration/iso8601_serializer.rb +51 -0
  156. data/lib/active_support/evented_file_update_checker.rb +199 -0
  157. data/lib/active_support/execution_wrapper.rb +126 -0
  158. data/lib/active_support/executor.rb +6 -0
  159. data/lib/active_support/file_update_checker.rb +157 -0
  160. data/lib/active_support/gem_version.rb +15 -0
  161. data/lib/active_support/gzip.rb +36 -0
  162. data/lib/active_support/hash_with_indifferent_access.rb +329 -0
  163. data/lib/active_support/i18n.rb +13 -0
  164. data/lib/active_support/i18n_railtie.rb +115 -0
  165. data/lib/active_support/inflections.rb +70 -0
  166. data/lib/active_support/inflector.rb +7 -0
  167. data/lib/active_support/inflector/inflections.rb +242 -0
  168. data/lib/active_support/inflector/methods.rb +390 -0
  169. data/lib/active_support/inflector/transliterate.rb +112 -0
  170. data/lib/active_support/json.rb +2 -0
  171. data/lib/active_support/json/decoding.rb +74 -0
  172. data/lib/active_support/json/encoding.rb +127 -0
  173. data/lib/active_support/key_generator.rb +71 -0
  174. data/lib/active_support/lazy_load_hooks.rb +76 -0
  175. data/lib/active_support/locale/en.yml +135 -0
  176. data/lib/active_support/log_subscriber.rb +109 -0
  177. data/lib/active_support/log_subscriber/test_helper.rb +104 -0
  178. data/lib/active_support/logger.rb +106 -0
  179. data/lib/active_support/logger_silence.rb +28 -0
  180. data/lib/active_support/logger_thread_safe_level.rb +31 -0
  181. data/lib/active_support/message_encryptor.rb +114 -0
  182. data/lib/active_support/message_verifier.rb +134 -0
  183. data/lib/active_support/multibyte.rb +21 -0
  184. data/lib/active_support/multibyte/chars.rb +231 -0
  185. data/lib/active_support/multibyte/unicode.rb +413 -0
  186. data/lib/active_support/notifications.rb +212 -0
  187. data/lib/active_support/notifications/fanout.rb +157 -0
  188. data/lib/active_support/notifications/instrumenter.rb +91 -0
  189. data/lib/active_support/number_helper.rb +368 -0
  190. data/lib/active_support/number_helper/number_converter.rb +182 -0
  191. data/lib/active_support/number_helper/number_to_currency_converter.rb +44 -0
  192. data/lib/active_support/number_helper/number_to_delimited_converter.rb +28 -0
  193. data/lib/active_support/number_helper/number_to_human_converter.rb +68 -0
  194. data/lib/active_support/number_helper/number_to_human_size_converter.rb +62 -0
  195. data/lib/active_support/number_helper/number_to_percentage_converter.rb +12 -0
  196. data/lib/active_support/number_helper/number_to_phone_converter.rb +58 -0
  197. data/lib/active_support/number_helper/number_to_rounded_converter.rb +92 -0
  198. data/lib/active_support/option_merger.rb +25 -0
  199. data/lib/active_support/ordered_hash.rb +48 -0
  200. data/lib/active_support/ordered_options.rb +81 -0
  201. data/lib/active_support/per_thread_registry.rb +58 -0
  202. data/lib/active_support/proxy_object.rb +13 -0
  203. data/lib/active_support/rails.rb +27 -0
  204. data/lib/active_support/railtie.rb +51 -0
  205. data/lib/active_support/reloader.rb +129 -0
  206. data/lib/active_support/rescuable.rb +173 -0
  207. data/lib/active_support/security_utils.rb +27 -0
  208. data/lib/active_support/string_inquirer.rb +26 -0
  209. data/lib/active_support/subscriber.rb +120 -0
  210. data/lib/active_support/tagged_logging.rb +77 -0
  211. data/lib/active_support/test_case.rb +88 -0
  212. data/lib/active_support/testing/assertions.rb +99 -0
  213. data/lib/active_support/testing/autorun.rb +5 -0
  214. data/lib/active_support/testing/constant_lookup.rb +50 -0
  215. data/lib/active_support/testing/declarative.rb +26 -0
  216. data/lib/active_support/testing/deprecation.rb +36 -0
  217. data/lib/active_support/testing/file_fixtures.rb +34 -0
  218. data/lib/active_support/testing/isolation.rb +115 -0
  219. data/lib/active_support/testing/method_call_assertions.rb +41 -0
  220. data/lib/active_support/testing/setup_and_teardown.rb +50 -0
  221. data/lib/active_support/testing/stream.rb +42 -0
  222. data/lib/active_support/testing/tagged_logging.rb +25 -0
  223. data/lib/active_support/testing/time_helpers.rb +136 -0
  224. data/lib/active_support/time.rb +18 -0
  225. data/lib/active_support/time_with_zone.rb +511 -0
  226. data/lib/active_support/values/time_zone.rb +484 -0
  227. data/lib/active_support/values/unicode_tables.dat +0 -0
  228. data/lib/active_support/version.rb +8 -0
  229. data/lib/active_support/xml_mini.rb +209 -0
  230. data/lib/active_support/xml_mini/jdom.rb +181 -0
  231. data/lib/active_support/xml_mini/libxml.rb +77 -0
  232. data/lib/active_support/xml_mini/libxmlsax.rb +82 -0
  233. data/lib/active_support/xml_mini/nokogiri.rb +81 -0
  234. data/lib/active_support/xml_mini/nokogirisax.rb +85 -0
  235. data/lib/active_support/xml_mini/rexml.rb +128 -0
  236. metadata +350 -0
@@ -0,0 +1,173 @@
1
+ require 'active_support/concern'
2
+ require 'active_support/core_ext/class/attribute'
3
+ require 'active_support/core_ext/string/inflections'
4
+
5
+ module ActiveSupport
6
+ # Rescuable module adds support for easier exception handling.
7
+ module Rescuable
8
+ extend Concern
9
+
10
+ included do
11
+ class_attribute :rescue_handlers
12
+ self.rescue_handlers = []
13
+ end
14
+
15
+ module ClassMethods
16
+ # Rescue exceptions raised in controller actions.
17
+ #
18
+ # <tt>rescue_from</tt> receives a series of exception classes or class
19
+ # names, and a trailing <tt>:with</tt> option with the name of a method
20
+ # or a Proc object to be called to handle them. Alternatively a block can
21
+ # be given.
22
+ #
23
+ # Handlers that take one argument will be called with the exception, so
24
+ # that the exception can be inspected when dealing with it.
25
+ #
26
+ # Handlers are inherited. They are searched from right to left, from
27
+ # bottom to top, and up the hierarchy. The handler of the first class for
28
+ # which <tt>exception.is_a?(klass)</tt> holds true is the one invoked, if
29
+ # any.
30
+ #
31
+ # class ApplicationController < ActionController::Base
32
+ # rescue_from User::NotAuthorized, with: :deny_access # self defined exception
33
+ # rescue_from ActiveRecord::RecordInvalid, with: :show_errors
34
+ #
35
+ # rescue_from 'MyAppError::Base' do |exception|
36
+ # render xml: exception, status: 500
37
+ # end
38
+ #
39
+ # protected
40
+ # def deny_access
41
+ # ...
42
+ # end
43
+ #
44
+ # def show_errors(exception)
45
+ # exception.record.new_record? ? ...
46
+ # end
47
+ # end
48
+ #
49
+ # Exceptions raised inside exception handlers are not propagated up.
50
+ def rescue_from(*klasses, with: nil, &block)
51
+ unless with
52
+ if block_given?
53
+ with = block
54
+ else
55
+ raise ArgumentError, 'Need a handler. Pass the with: keyword argument or provide a block.'
56
+ end
57
+ end
58
+
59
+ klasses.each do |klass|
60
+ key = if klass.is_a?(Module) && klass.respond_to?(:===)
61
+ klass.name
62
+ elsif klass.is_a?(String)
63
+ klass
64
+ else
65
+ raise ArgumentError, "#{klass.inspect} must be an Exception class or a String referencing an Exception class"
66
+ end
67
+
68
+ # Put the new handler at the end because the list is read in reverse.
69
+ self.rescue_handlers += [[key, with]]
70
+ end
71
+ end
72
+
73
+ # Matches an exception to a handler based on the exception class.
74
+ #
75
+ # If no handler matches the exception, check for a handler matching the
76
+ # (optional) exception.cause. If no handler matches the exception or its
77
+ # cause, this returns nil so you can deal with unhandled exceptions.
78
+ # Be sure to re-raise unhandled exceptions if this is what you expect.
79
+ #
80
+ # begin
81
+ # …
82
+ # rescue => exception
83
+ # rescue_with_handler(exception) || raise
84
+ # end
85
+ #
86
+ # Returns the exception if it was handled and +nil+ if it was not.
87
+ def rescue_with_handler(exception, object: self, visited_exceptions: [])
88
+ visited_exceptions << exception
89
+
90
+ if handler = handler_for_rescue(exception, object: object)
91
+ handler.call exception
92
+ exception
93
+ elsif exception
94
+ if visited_exceptions.include?(exception.cause)
95
+ nil
96
+ else
97
+ rescue_with_handler(exception.cause, object: object, visited_exceptions: visited_exceptions)
98
+ end
99
+ end
100
+ end
101
+
102
+ def handler_for_rescue(exception, object: self) #:nodoc:
103
+ case rescuer = find_rescue_handler(exception)
104
+ when Symbol
105
+ method = object.method(rescuer)
106
+ if method.arity == 0
107
+ -> e { method.call }
108
+ else
109
+ method
110
+ end
111
+ when Proc
112
+ if rescuer.arity == 0
113
+ -> e { object.instance_exec(&rescuer) }
114
+ else
115
+ -> e { object.instance_exec(e, &rescuer) }
116
+ end
117
+ end
118
+ end
119
+
120
+ private
121
+ def find_rescue_handler(exception)
122
+ if exception
123
+ # Handlers are in order of declaration but the most recently declared
124
+ # is the highest priority match, so we search for matching handlers
125
+ # in reverse.
126
+ _, handler = rescue_handlers.reverse_each.detect do |class_or_name, _|
127
+ if klass = constantize_rescue_handler_class(class_or_name)
128
+ klass === exception
129
+ end
130
+ end
131
+
132
+ handler
133
+ end
134
+ end
135
+
136
+ def constantize_rescue_handler_class(class_or_name)
137
+ case class_or_name
138
+ when String, Symbol
139
+ begin
140
+ # Try a lexical lookup first since we support
141
+ #
142
+ # class Super
143
+ # rescue_from 'Error', with: …
144
+ # end
145
+ #
146
+ # class Sub
147
+ # class Error < StandardError; end
148
+ # end
149
+ #
150
+ # so an Error raised in Sub will hit the 'Error' handler.
151
+ const_get class_or_name
152
+ rescue NameError
153
+ class_or_name.safe_constantize
154
+ end
155
+ else
156
+ class_or_name
157
+ end
158
+ end
159
+ end
160
+
161
+ # Delegates to the class method, but uses the instance as the subject for
162
+ # rescue_from handlers (method calls, instance_exec blocks).
163
+ def rescue_with_handler(exception)
164
+ self.class.rescue_with_handler exception, object: self
165
+ end
166
+
167
+ # Internal handler lookup. Delegates to class method. Some libraries call
168
+ # this directly, so keeping it around for compatibility.
169
+ def handler_for_rescue(exception) #:nodoc:
170
+ self.class.handler_for_rescue exception, object: self
171
+ end
172
+ end
173
+ end
@@ -0,0 +1,27 @@
1
+ require 'digest'
2
+
3
+ module ActiveSupport
4
+ module SecurityUtils
5
+ # Constant time string comparison.
6
+ #
7
+ # The values compared should be of fixed length, such as strings
8
+ # that have already been processed by HMAC. This should not be used
9
+ # on variable length plaintext strings because it could leak length info
10
+ # via timing attacks.
11
+ def secure_compare(a, b)
12
+ return false unless a.bytesize == b.bytesize
13
+
14
+ l = a.unpack "C#{a.bytesize}"
15
+
16
+ res = 0
17
+ b.each_byte { |byte| res |= byte ^ l.shift }
18
+ res == 0
19
+ end
20
+ module_function :secure_compare
21
+
22
+ def variable_size_secure_compare(a, b) # :nodoc:
23
+ secure_compare(::Digest::SHA256.hexdigest(a), ::Digest::SHA256.hexdigest(b))
24
+ end
25
+ module_function :variable_size_secure_compare
26
+ end
27
+ end
@@ -0,0 +1,26 @@
1
+ module ActiveSupport
2
+ # Wrapping a string in this class gives you a prettier way to test
3
+ # for equality. The value returned by <tt>Rails.env</tt> is wrapped
4
+ # in a StringInquirer object, so instead of calling this:
5
+ #
6
+ # Rails.env == 'production'
7
+ #
8
+ # you can call this:
9
+ #
10
+ # Rails.env.production?
11
+ class StringInquirer < String
12
+ private
13
+
14
+ def respond_to_missing?(method_name, include_private = false)
15
+ method_name[-1] == '?'
16
+ end
17
+
18
+ def method_missing(method_name, *arguments)
19
+ if method_name[-1] == '?'
20
+ self == method_name[0..-2]
21
+ else
22
+ super
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,120 @@
1
+ require 'active_support/per_thread_registry'
2
+
3
+ module ActiveSupport
4
+ # ActiveSupport::Subscriber is an object set to consume
5
+ # ActiveSupport::Notifications. The subscriber dispatches notifications to
6
+ # a registered object based on its given namespace.
7
+ #
8
+ # An example would be an Active Record subscriber responsible for collecting
9
+ # statistics about queries:
10
+ #
11
+ # module ActiveRecord
12
+ # class StatsSubscriber < ActiveSupport::Subscriber
13
+ # attach_to :active_record
14
+ #
15
+ # def sql(event)
16
+ # Statsd.timing("sql.#{event.payload[:name]}", event.duration)
17
+ # end
18
+ # end
19
+ # end
20
+ #
21
+ # After configured, whenever a "sql.active_record" notification is published,
22
+ # it will properly dispatch the event (ActiveSupport::Notifications::Event) to
23
+ # the +sql+ method.
24
+ class Subscriber
25
+ class << self
26
+
27
+ # Attach the subscriber to a namespace.
28
+ def attach_to(namespace, subscriber=new, notifier=ActiveSupport::Notifications)
29
+ @namespace = namespace
30
+ @subscriber = subscriber
31
+ @notifier = notifier
32
+
33
+ subscribers << subscriber
34
+
35
+ # Add event subscribers for all existing methods on the class.
36
+ subscriber.public_methods(false).each do |event|
37
+ add_event_subscriber(event)
38
+ end
39
+ end
40
+
41
+ # Adds event subscribers for all new methods added to the class.
42
+ def method_added(event)
43
+ # Only public methods are added as subscribers, and only if a notifier
44
+ # has been set up. This means that subscribers will only be set up for
45
+ # classes that call #attach_to.
46
+ if public_method_defined?(event) && notifier
47
+ add_event_subscriber(event)
48
+ end
49
+ end
50
+
51
+ def subscribers
52
+ @@subscribers ||= []
53
+ end
54
+
55
+ protected
56
+
57
+ attr_reader :subscriber, :notifier, :namespace
58
+
59
+ def add_event_subscriber(event)
60
+ return if %w{ start finish }.include?(event.to_s)
61
+
62
+ pattern = "#{event}.#{namespace}"
63
+
64
+ # Don't add multiple subscribers (eg. if methods are redefined).
65
+ return if subscriber.patterns.include?(pattern)
66
+
67
+ subscriber.patterns << pattern
68
+ notifier.subscribe(pattern, subscriber)
69
+ end
70
+ end
71
+
72
+ attr_reader :patterns # :nodoc:
73
+
74
+ def initialize
75
+ @queue_key = [self.class.name, object_id].join "-"
76
+ @patterns = []
77
+ super
78
+ end
79
+
80
+ def start(name, id, payload)
81
+ e = ActiveSupport::Notifications::Event.new(name, Time.now, nil, id, payload)
82
+ parent = event_stack.last
83
+ parent << e if parent
84
+
85
+ event_stack.push e
86
+ end
87
+
88
+ def finish(name, id, payload)
89
+ finished = Time.now
90
+ event = event_stack.pop
91
+ event.end = finished
92
+ event.payload.merge!(payload)
93
+
94
+ method = name.split('.'.freeze).first
95
+ send(method, event)
96
+ end
97
+
98
+ private
99
+
100
+ def event_stack
101
+ SubscriberQueueRegistry.instance.get_queue(@queue_key)
102
+ end
103
+ end
104
+
105
+ # This is a registry for all the event stacks kept for subscribers.
106
+ #
107
+ # See the documentation of <tt>ActiveSupport::PerThreadRegistry</tt>
108
+ # for further details.
109
+ class SubscriberQueueRegistry # :nodoc:
110
+ extend PerThreadRegistry
111
+
112
+ def initialize
113
+ @registry = {}
114
+ end
115
+
116
+ def get_queue(queue_key)
117
+ @registry[queue_key] ||= []
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,77 @@
1
+ require 'active_support/core_ext/module/delegation'
2
+ require 'active_support/core_ext/object/blank'
3
+ require 'logger'
4
+ require 'active_support/logger'
5
+
6
+ module ActiveSupport
7
+ # Wraps any standard Logger object to provide tagging capabilities.
8
+ #
9
+ # logger = ActiveSupport::TaggedLogging.new(Logger.new(STDOUT))
10
+ # logger.tagged('BCX') { logger.info 'Stuff' } # Logs "[BCX] Stuff"
11
+ # logger.tagged('BCX', "Jason") { logger.info 'Stuff' } # Logs "[BCX] [Jason] Stuff"
12
+ # logger.tagged('BCX') { logger.tagged('Jason') { logger.info 'Stuff' } } # Logs "[BCX] [Jason] Stuff"
13
+ #
14
+ # This is used by the default Rails.logger as configured by Railties to make
15
+ # it easy to stamp log lines with subdomains, request ids, and anything else
16
+ # to aid debugging of multi-user production applications.
17
+ module TaggedLogging
18
+ module Formatter # :nodoc:
19
+ # This method is invoked when a log event occurs.
20
+ def call(severity, timestamp, progname, msg)
21
+ super(severity, timestamp, progname, "#{tags_text}#{msg}")
22
+ end
23
+
24
+ def tagged(*tags)
25
+ new_tags = push_tags(*tags)
26
+ yield self
27
+ ensure
28
+ pop_tags(new_tags.size)
29
+ end
30
+
31
+ def push_tags(*tags)
32
+ tags.flatten.reject(&:blank?).tap do |new_tags|
33
+ current_tags.concat new_tags
34
+ end
35
+ end
36
+
37
+ def pop_tags(size = 1)
38
+ current_tags.pop size
39
+ end
40
+
41
+ def clear_tags!
42
+ current_tags.clear
43
+ end
44
+
45
+ def current_tags
46
+ # We use our object ID here to avoid conflicting with other instances
47
+ thread_key = @thread_key ||= "activesupport_tagged_logging_tags:#{object_id}".freeze
48
+ Thread.current[thread_key] ||= []
49
+ end
50
+
51
+ def tags_text
52
+ tags = current_tags
53
+ if tags.any?
54
+ tags.collect { |tag| "[#{tag}] " }.join
55
+ end
56
+ end
57
+ end
58
+
59
+ def self.new(logger)
60
+ # Ensure we set a default formatter so we aren't extending nil!
61
+ logger.formatter ||= ActiveSupport::Logger::SimpleFormatter.new
62
+ logger.formatter.extend Formatter
63
+ logger.extend(self)
64
+ end
65
+
66
+ delegate :push_tags, :pop_tags, :clear_tags!, to: :formatter
67
+
68
+ def tagged(*tags)
69
+ formatter.tagged(*tags) { yield self }
70
+ end
71
+
72
+ def flush
73
+ clear_tags!
74
+ super if defined?(super)
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,88 @@
1
+ gem 'minitest' # make sure we get the gem, not stdlib
2
+ require 'minitest'
3
+ require 'active_support/testing/tagged_logging'
4
+ require 'active_support/testing/setup_and_teardown'
5
+ require 'active_support/testing/assertions'
6
+ require 'active_support/testing/deprecation'
7
+ require 'active_support/testing/declarative'
8
+ require 'active_support/testing/isolation'
9
+ require 'active_support/testing/constant_lookup'
10
+ require 'active_support/testing/time_helpers'
11
+ require 'active_support/testing/file_fixtures'
12
+ require 'active_support/core_ext/kernel/reporting'
13
+
14
+ module ActiveSupport
15
+ class TestCase < ::Minitest::Test
16
+ Assertion = Minitest::Assertion
17
+
18
+ class << self
19
+ # Sets the order in which test cases are run.
20
+ #
21
+ # ActiveSupport::TestCase.test_order = :random # => :random
22
+ #
23
+ # Valid values are:
24
+ # * +:random+ (to run tests in random order)
25
+ # * +:parallel+ (to run tests in parallel)
26
+ # * +:sorted+ (to run tests alphabetically by method name)
27
+ # * +:alpha+ (equivalent to +:sorted+)
28
+ def test_order=(new_order)
29
+ ActiveSupport.test_order = new_order
30
+ end
31
+
32
+ # Returns the order in which test cases are run.
33
+ #
34
+ # ActiveSupport::TestCase.test_order # => :random
35
+ #
36
+ # Possible values are +:random+, +:parallel+, +:alpha+, +:sorted+.
37
+ # Defaults to +:random+.
38
+ def test_order
39
+ ActiveSupport.test_order ||= :random
40
+ end
41
+ end
42
+
43
+ alias_method :method_name, :name
44
+
45
+ include ActiveSupport::Testing::TaggedLogging
46
+ include ActiveSupport::Testing::SetupAndTeardown
47
+ include ActiveSupport::Testing::Assertions
48
+ include ActiveSupport::Testing::Deprecation
49
+ include ActiveSupport::Testing::TimeHelpers
50
+ include ActiveSupport::Testing::FileFixtures
51
+ extend ActiveSupport::Testing::Declarative
52
+
53
+ # test/unit backwards compatibility methods
54
+ alias :assert_raise :assert_raises
55
+ alias :assert_not_empty :refute_empty
56
+ alias :assert_not_equal :refute_equal
57
+ alias :assert_not_in_delta :refute_in_delta
58
+ alias :assert_not_in_epsilon :refute_in_epsilon
59
+ alias :assert_not_includes :refute_includes
60
+ alias :assert_not_instance_of :refute_instance_of
61
+ alias :assert_not_kind_of :refute_kind_of
62
+ alias :assert_no_match :refute_match
63
+ alias :assert_not_nil :refute_nil
64
+ alias :assert_not_operator :refute_operator
65
+ alias :assert_not_predicate :refute_predicate
66
+ alias :assert_not_respond_to :refute_respond_to
67
+ alias :assert_not_same :refute_same
68
+
69
+
70
+ # Assertion that the block should not raise an exception.
71
+ #
72
+ # Passes if evaluated code in the yielded block raises no exception.
73
+ #
74
+ # assert_nothing_raised do
75
+ # perform_service(param: 'no_exception')
76
+ # end
77
+ def assert_nothing_raised(*args)
78
+ if args.present?
79
+ ActiveSupport::Deprecation.warn(
80
+ "Passing arguments to assert_nothing_raised " \
81
+ "is deprecated and will be removed in Rails 5.1.")
82
+ end
83
+ yield
84
+ end
85
+
86
+ ActiveSupport.run_load_hooks(:active_support_test_case, self)
87
+ end
88
+ end