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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +1013 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +39 -0
- data/lib/active_support.rb +99 -0
- data/lib/active_support/all.rb +3 -0
- data/lib/active_support/array_inquirer.rb +44 -0
- data/lib/active_support/backtrace_cleaner.rb +103 -0
- data/lib/active_support/benchmarkable.rb +49 -0
- data/lib/active_support/builder.rb +6 -0
- data/lib/active_support/cache.rb +701 -0
- data/lib/active_support/cache/file_store.rb +204 -0
- data/lib/active_support/cache/mem_cache_store.rb +207 -0
- data/lib/active_support/cache/memory_store.rb +167 -0
- data/lib/active_support/cache/null_store.rb +41 -0
- data/lib/active_support/cache/strategy/local_cache.rb +172 -0
- data/lib/active_support/cache/strategy/local_cache_middleware.rb +44 -0
- data/lib/active_support/callbacks.rb +791 -0
- data/lib/active_support/concern.rb +142 -0
- data/lib/active_support/concurrency/latch.rb +26 -0
- data/lib/active_support/concurrency/share_lock.rb +226 -0
- data/lib/active_support/configurable.rb +148 -0
- data/lib/active_support/core_ext.rb +4 -0
- data/lib/active_support/core_ext/array.rb +7 -0
- data/lib/active_support/core_ext/array/access.rb +90 -0
- data/lib/active_support/core_ext/array/conversions.rb +211 -0
- data/lib/active_support/core_ext/array/extract_options.rb +29 -0
- data/lib/active_support/core_ext/array/grouping.rb +107 -0
- data/lib/active_support/core_ext/array/inquiry.rb +17 -0
- data/lib/active_support/core_ext/array/prepend_and_append.rb +7 -0
- data/lib/active_support/core_ext/array/wrap.rb +46 -0
- data/lib/active_support/core_ext/benchmark.rb +14 -0
- data/lib/active_support/core_ext/big_decimal.rb +1 -0
- data/lib/active_support/core_ext/big_decimal/conversions.rb +14 -0
- data/lib/active_support/core_ext/class.rb +2 -0
- data/lib/active_support/core_ext/class/attribute.rb +128 -0
- data/lib/active_support/core_ext/class/attribute_accessors.rb +4 -0
- data/lib/active_support/core_ext/class/subclasses.rb +41 -0
- data/lib/active_support/core_ext/date.rb +5 -0
- data/lib/active_support/core_ext/date/acts_like.rb +8 -0
- data/lib/active_support/core_ext/date/blank.rb +12 -0
- data/lib/active_support/core_ext/date/calculations.rb +143 -0
- data/lib/active_support/core_ext/date/conversions.rb +95 -0
- data/lib/active_support/core_ext/date/zones.rb +6 -0
- data/lib/active_support/core_ext/date_and_time/calculations.rb +335 -0
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +14 -0
- data/lib/active_support/core_ext/date_and_time/zones.rb +40 -0
- data/lib/active_support/core_ext/date_time.rb +5 -0
- data/lib/active_support/core_ext/date_time/acts_like.rb +14 -0
- data/lib/active_support/core_ext/date_time/blank.rb +12 -0
- data/lib/active_support/core_ext/date_time/calculations.rb +199 -0
- data/lib/active_support/core_ext/date_time/compatibility.rb +16 -0
- data/lib/active_support/core_ext/date_time/conversions.rb +105 -0
- data/lib/active_support/core_ext/digest/uuid.rb +51 -0
- data/lib/active_support/core_ext/enumerable.rb +146 -0
- data/lib/active_support/core_ext/file.rb +1 -0
- data/lib/active_support/core_ext/file/atomic.rb +68 -0
- data/lib/active_support/core_ext/hash.rb +9 -0
- data/lib/active_support/core_ext/hash/compact.rb +24 -0
- data/lib/active_support/core_ext/hash/conversions.rb +262 -0
- data/lib/active_support/core_ext/hash/deep_merge.rb +38 -0
- data/lib/active_support/core_ext/hash/except.rb +22 -0
- data/lib/active_support/core_ext/hash/indifferent_access.rb +23 -0
- data/lib/active_support/core_ext/hash/keys.rb +170 -0
- data/lib/active_support/core_ext/hash/reverse_merge.rb +22 -0
- data/lib/active_support/core_ext/hash/slice.rb +48 -0
- data/lib/active_support/core_ext/hash/transform_values.rb +29 -0
- data/lib/active_support/core_ext/integer.rb +3 -0
- data/lib/active_support/core_ext/integer/inflections.rb +29 -0
- data/lib/active_support/core_ext/integer/multiple.rb +10 -0
- data/lib/active_support/core_ext/integer/time.rb +29 -0
- data/lib/active_support/core_ext/kernel.rb +4 -0
- data/lib/active_support/core_ext/kernel/agnostics.rb +11 -0
- data/lib/active_support/core_ext/kernel/concern.rb +12 -0
- data/lib/active_support/core_ext/kernel/debugger.rb +3 -0
- data/lib/active_support/core_ext/kernel/reporting.rb +43 -0
- data/lib/active_support/core_ext/kernel/singleton_class.rb +6 -0
- data/lib/active_support/core_ext/load_error.rb +31 -0
- data/lib/active_support/core_ext/marshal.rb +22 -0
- data/lib/active_support/core_ext/module.rb +12 -0
- data/lib/active_support/core_ext/module/aliasing.rb +74 -0
- data/lib/active_support/core_ext/module/anonymous.rb +28 -0
- data/lib/active_support/core_ext/module/attr_internal.rb +36 -0
- data/lib/active_support/core_ext/module/attribute_accessors.rb +212 -0
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +141 -0
- data/lib/active_support/core_ext/module/concerning.rb +135 -0
- data/lib/active_support/core_ext/module/delegation.rb +216 -0
- data/lib/active_support/core_ext/module/deprecation.rb +23 -0
- data/lib/active_support/core_ext/module/introspection.rb +68 -0
- data/lib/active_support/core_ext/module/method_transplanting.rb +3 -0
- data/lib/active_support/core_ext/module/qualified_const.rb +70 -0
- data/lib/active_support/core_ext/module/reachable.rb +8 -0
- data/lib/active_support/core_ext/module/remove_method.rb +35 -0
- data/lib/active_support/core_ext/name_error.rb +31 -0
- data/lib/active_support/core_ext/numeric.rb +4 -0
- data/lib/active_support/core_ext/numeric/bytes.rb +64 -0
- data/lib/active_support/core_ext/numeric/conversions.rb +144 -0
- data/lib/active_support/core_ext/numeric/inquiry.rb +26 -0
- data/lib/active_support/core_ext/numeric/time.rb +74 -0
- data/lib/active_support/core_ext/object.rb +14 -0
- data/lib/active_support/core_ext/object/acts_like.rb +10 -0
- data/lib/active_support/core_ext/object/blank.rb +143 -0
- data/lib/active_support/core_ext/object/conversions.rb +4 -0
- data/lib/active_support/core_ext/object/deep_dup.rb +53 -0
- data/lib/active_support/core_ext/object/duplicable.rb +124 -0
- data/lib/active_support/core_ext/object/inclusion.rb +27 -0
- data/lib/active_support/core_ext/object/instance_variables.rb +28 -0
- data/lib/active_support/core_ext/object/json.rb +205 -0
- data/lib/active_support/core_ext/object/to_param.rb +1 -0
- data/lib/active_support/core_ext/object/to_query.rb +84 -0
- data/lib/active_support/core_ext/object/try.rb +146 -0
- data/lib/active_support/core_ext/object/with_options.rb +69 -0
- data/lib/active_support/core_ext/range.rb +4 -0
- data/lib/active_support/core_ext/range/conversions.rb +31 -0
- data/lib/active_support/core_ext/range/each.rb +21 -0
- data/lib/active_support/core_ext/range/include_range.rb +23 -0
- data/lib/active_support/core_ext/range/overlaps.rb +8 -0
- data/lib/active_support/core_ext/regexp.rb +5 -0
- data/lib/active_support/core_ext/securerandom.rb +23 -0
- data/lib/active_support/core_ext/string.rb +13 -0
- data/lib/active_support/core_ext/string/access.rb +104 -0
- data/lib/active_support/core_ext/string/behavior.rb +6 -0
- data/lib/active_support/core_ext/string/conversions.rb +57 -0
- data/lib/active_support/core_ext/string/exclude.rb +11 -0
- data/lib/active_support/core_ext/string/filters.rb +102 -0
- data/lib/active_support/core_ext/string/indent.rb +43 -0
- data/lib/active_support/core_ext/string/inflections.rb +244 -0
- data/lib/active_support/core_ext/string/inquiry.rb +13 -0
- data/lib/active_support/core_ext/string/multibyte.rb +53 -0
- data/lib/active_support/core_ext/string/output_safety.rb +260 -0
- data/lib/active_support/core_ext/string/starts_ends_with.rb +4 -0
- data/lib/active_support/core_ext/string/strip.rb +23 -0
- data/lib/active_support/core_ext/string/zones.rb +14 -0
- data/lib/active_support/core_ext/struct.rb +3 -0
- data/lib/active_support/core_ext/time.rb +5 -0
- data/lib/active_support/core_ext/time/acts_like.rb +8 -0
- data/lib/active_support/core_ext/time/calculations.rb +290 -0
- data/lib/active_support/core_ext/time/compatibility.rb +14 -0
- data/lib/active_support/core_ext/time/conversions.rb +67 -0
- data/lib/active_support/core_ext/time/marshal.rb +3 -0
- data/lib/active_support/core_ext/time/zones.rb +111 -0
- data/lib/active_support/core_ext/uri.rb +24 -0
- data/lib/active_support/dependencies.rb +755 -0
- data/lib/active_support/dependencies/autoload.rb +77 -0
- data/lib/active_support/dependencies/interlock.rb +55 -0
- data/lib/active_support/deprecation.rb +43 -0
- data/lib/active_support/deprecation/behaviors.rb +90 -0
- data/lib/active_support/deprecation/instance_delegator.rb +37 -0
- data/lib/active_support/deprecation/method_wrappers.rb +70 -0
- data/lib/active_support/deprecation/proxy_wrappers.rb +149 -0
- data/lib/active_support/deprecation/reporting.rb +112 -0
- data/lib/active_support/descendants_tracker.rb +60 -0
- data/lib/active_support/duration.rb +235 -0
- data/lib/active_support/duration/iso8601_parser.rb +122 -0
- data/lib/active_support/duration/iso8601_serializer.rb +51 -0
- data/lib/active_support/evented_file_update_checker.rb +199 -0
- data/lib/active_support/execution_wrapper.rb +126 -0
- data/lib/active_support/executor.rb +6 -0
- data/lib/active_support/file_update_checker.rb +157 -0
- data/lib/active_support/gem_version.rb +15 -0
- data/lib/active_support/gzip.rb +36 -0
- data/lib/active_support/hash_with_indifferent_access.rb +329 -0
- data/lib/active_support/i18n.rb +13 -0
- data/lib/active_support/i18n_railtie.rb +115 -0
- data/lib/active_support/inflections.rb +70 -0
- data/lib/active_support/inflector.rb +7 -0
- data/lib/active_support/inflector/inflections.rb +242 -0
- data/lib/active_support/inflector/methods.rb +390 -0
- data/lib/active_support/inflector/transliterate.rb +112 -0
- data/lib/active_support/json.rb +2 -0
- data/lib/active_support/json/decoding.rb +74 -0
- data/lib/active_support/json/encoding.rb +127 -0
- data/lib/active_support/key_generator.rb +71 -0
- data/lib/active_support/lazy_load_hooks.rb +76 -0
- data/lib/active_support/locale/en.yml +135 -0
- data/lib/active_support/log_subscriber.rb +109 -0
- data/lib/active_support/log_subscriber/test_helper.rb +104 -0
- data/lib/active_support/logger.rb +106 -0
- data/lib/active_support/logger_silence.rb +28 -0
- data/lib/active_support/logger_thread_safe_level.rb +31 -0
- data/lib/active_support/message_encryptor.rb +114 -0
- data/lib/active_support/message_verifier.rb +134 -0
- data/lib/active_support/multibyte.rb +21 -0
- data/lib/active_support/multibyte/chars.rb +231 -0
- data/lib/active_support/multibyte/unicode.rb +413 -0
- data/lib/active_support/notifications.rb +212 -0
- data/lib/active_support/notifications/fanout.rb +157 -0
- data/lib/active_support/notifications/instrumenter.rb +91 -0
- data/lib/active_support/number_helper.rb +368 -0
- data/lib/active_support/number_helper/number_converter.rb +182 -0
- data/lib/active_support/number_helper/number_to_currency_converter.rb +44 -0
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +28 -0
- data/lib/active_support/number_helper/number_to_human_converter.rb +68 -0
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +62 -0
- data/lib/active_support/number_helper/number_to_percentage_converter.rb +12 -0
- data/lib/active_support/number_helper/number_to_phone_converter.rb +58 -0
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +92 -0
- data/lib/active_support/option_merger.rb +25 -0
- data/lib/active_support/ordered_hash.rb +48 -0
- data/lib/active_support/ordered_options.rb +81 -0
- data/lib/active_support/per_thread_registry.rb +58 -0
- data/lib/active_support/proxy_object.rb +13 -0
- data/lib/active_support/rails.rb +27 -0
- data/lib/active_support/railtie.rb +51 -0
- data/lib/active_support/reloader.rb +129 -0
- data/lib/active_support/rescuable.rb +173 -0
- data/lib/active_support/security_utils.rb +27 -0
- data/lib/active_support/string_inquirer.rb +26 -0
- data/lib/active_support/subscriber.rb +120 -0
- data/lib/active_support/tagged_logging.rb +77 -0
- data/lib/active_support/test_case.rb +88 -0
- data/lib/active_support/testing/assertions.rb +99 -0
- data/lib/active_support/testing/autorun.rb +5 -0
- data/lib/active_support/testing/constant_lookup.rb +50 -0
- data/lib/active_support/testing/declarative.rb +26 -0
- data/lib/active_support/testing/deprecation.rb +36 -0
- data/lib/active_support/testing/file_fixtures.rb +34 -0
- data/lib/active_support/testing/isolation.rb +115 -0
- data/lib/active_support/testing/method_call_assertions.rb +41 -0
- data/lib/active_support/testing/setup_and_teardown.rb +50 -0
- data/lib/active_support/testing/stream.rb +42 -0
- data/lib/active_support/testing/tagged_logging.rb +25 -0
- data/lib/active_support/testing/time_helpers.rb +136 -0
- data/lib/active_support/time.rb +18 -0
- data/lib/active_support/time_with_zone.rb +511 -0
- data/lib/active_support/values/time_zone.rb +484 -0
- data/lib/active_support/values/unicode_tables.dat +0 -0
- data/lib/active_support/version.rb +8 -0
- data/lib/active_support/xml_mini.rb +209 -0
- data/lib/active_support/xml_mini/jdom.rb +181 -0
- data/lib/active_support/xml_mini/libxml.rb +77 -0
- data/lib/active_support/xml_mini/libxmlsax.rb +82 -0
- data/lib/active_support/xml_mini/nokogiri.rb +81 -0
- data/lib/active_support/xml_mini/nokogirisax.rb +85 -0
- data/lib/active_support/xml_mini/rexml.rb +128 -0
- 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
|