activesupport 5.1.7 → 5.2.0.beta1
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 +5 -5
- data/CHANGELOG.md +303 -617
- data/README.rdoc +1 -1
- data/lib/active_support.rb +3 -12
- data/lib/active_support/all.rb +2 -0
- data/lib/active_support/array_inquirer.rb +2 -0
- data/lib/active_support/backtrace_cleaner.rb +2 -0
- data/lib/active_support/benchmarkable.rb +2 -0
- data/lib/active_support/builder.rb +2 -0
- data/lib/active_support/cache.rb +127 -58
- data/lib/active_support/cache/file_store.rb +4 -3
- data/lib/active_support/cache/mem_cache_store.rb +12 -4
- data/lib/active_support/cache/memory_store.rb +2 -0
- data/lib/active_support/cache/null_store.rb +2 -0
- data/lib/active_support/cache/redis_cache_store.rb +404 -0
- data/lib/active_support/cache/strategy/local_cache.rb +9 -2
- data/lib/active_support/cache/strategy/local_cache_middleware.rb +2 -0
- data/lib/active_support/callbacks.rb +26 -37
- data/lib/active_support/concern.rb +3 -1
- data/lib/active_support/concurrency/share_lock.rb +2 -0
- data/lib/active_support/configurable.rb +2 -0
- data/lib/active_support/core_ext.rb +3 -1
- data/lib/active_support/core_ext/array.rb +2 -0
- data/lib/active_support/core_ext/array/access.rb +4 -2
- data/lib/active_support/core_ext/array/conversions.rb +2 -0
- data/lib/active_support/core_ext/array/extract_options.rb +2 -0
- data/lib/active_support/core_ext/array/grouping.rb +2 -0
- data/lib/active_support/core_ext/array/inquiry.rb +2 -0
- data/lib/active_support/core_ext/array/prepend_and_append.rb +4 -2
- data/lib/active_support/core_ext/array/wrap.rb +2 -0
- data/lib/active_support/core_ext/benchmark.rb +2 -0
- data/lib/active_support/core_ext/big_decimal.rb +2 -0
- data/lib/active_support/core_ext/big_decimal/conversions.rb +2 -0
- data/lib/active_support/core_ext/class.rb +2 -0
- data/lib/active_support/core_ext/class/attribute.rb +34 -16
- data/lib/active_support/core_ext/class/attribute_accessors.rb +2 -0
- data/lib/active_support/core_ext/class/subclasses.rb +1 -2
- data/lib/active_support/core_ext/date.rb +2 -0
- data/lib/active_support/core_ext/date/acts_like.rb +2 -0
- data/lib/active_support/core_ext/date/blank.rb +2 -0
- data/lib/active_support/core_ext/date/calculations.rb +2 -0
- data/lib/active_support/core_ext/date/conversions.rb +10 -9
- data/lib/active_support/core_ext/date/zones.rb +2 -0
- data/lib/active_support/core_ext/date_and_time/calculations.rb +42 -16
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +3 -1
- data/lib/active_support/core_ext/date_and_time/zones.rb +2 -0
- data/lib/active_support/core_ext/date_time.rb +2 -0
- data/lib/active_support/core_ext/date_time/acts_like.rb +2 -0
- data/lib/active_support/core_ext/date_time/blank.rb +2 -0
- data/lib/active_support/core_ext/date_time/calculations.rb +2 -0
- data/lib/active_support/core_ext/date_time/compatibility.rb +6 -4
- data/lib/active_support/core_ext/date_time/conversions.rb +2 -0
- data/lib/active_support/core_ext/digest/uuid.rb +3 -1
- data/lib/active_support/core_ext/enumerable.rb +3 -1
- data/lib/active_support/core_ext/file.rb +2 -0
- data/lib/active_support/core_ext/file/atomic.rb +2 -0
- data/lib/active_support/core_ext/hash.rb +2 -0
- data/lib/active_support/core_ext/hash/compact.rb +2 -0
- data/lib/active_support/core_ext/hash/conversions.rb +2 -0
- data/lib/active_support/core_ext/hash/deep_merge.rb +8 -12
- data/lib/active_support/core_ext/hash/except.rb +2 -0
- data/lib/active_support/core_ext/hash/indifferent_access.rb +2 -0
- data/lib/active_support/core_ext/hash/keys.rb +2 -0
- data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
- data/lib/active_support/core_ext/hash/slice.rb +4 -4
- data/lib/active_support/core_ext/hash/transform_values.rb +2 -0
- data/lib/active_support/core_ext/integer.rb +2 -0
- data/lib/active_support/core_ext/integer/inflections.rb +2 -0
- data/lib/active_support/core_ext/integer/multiple.rb +2 -0
- data/lib/active_support/core_ext/integer/time.rb +7 -14
- data/lib/active_support/core_ext/kernel.rb +2 -0
- data/lib/active_support/core_ext/kernel/agnostics.rb +2 -0
- data/lib/active_support/core_ext/kernel/concern.rb +2 -0
- data/lib/active_support/core_ext/kernel/reporting.rb +2 -0
- data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
- data/lib/active_support/core_ext/load_error.rb +2 -7
- data/lib/active_support/core_ext/marshal.rb +2 -0
- data/lib/active_support/core_ext/module.rb +3 -0
- data/lib/active_support/core_ext/module/aliasing.rb +2 -0
- data/lib/active_support/core_ext/module/anonymous.rb +2 -0
- data/lib/active_support/core_ext/module/attr_internal.rb +2 -0
- data/lib/active_support/core_ext/module/attribute_accessors.rb +21 -24
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +2 -0
- data/lib/active_support/core_ext/module/concerning.rb +2 -0
- data/lib/active_support/core_ext/module/delegation.rb +29 -24
- data/lib/active_support/core_ext/module/deprecation.rb +2 -0
- data/lib/active_support/core_ext/module/introspection.rb +2 -0
- data/lib/active_support/core_ext/module/reachable.rb +3 -0
- data/lib/active_support/core_ext/module/redefine_method.rb +49 -0
- data/lib/active_support/core_ext/module/remove_method.rb +5 -23
- data/lib/active_support/core_ext/name_error.rb +2 -0
- data/lib/active_support/core_ext/numeric.rb +2 -0
- data/lib/active_support/core_ext/numeric/bytes.rb +2 -0
- data/lib/active_support/core_ext/numeric/conversions.rb +9 -7
- data/lib/active_support/core_ext/numeric/inquiry.rb +2 -0
- data/lib/active_support/core_ext/numeric/time.rb +7 -15
- data/lib/active_support/core_ext/object.rb +2 -0
- data/lib/active_support/core_ext/object/acts_like.rb +12 -1
- data/lib/active_support/core_ext/object/blank.rb +2 -0
- data/lib/active_support/core_ext/object/conversions.rb +2 -0
- data/lib/active_support/core_ext/object/deep_dup.rb +2 -0
- data/lib/active_support/core_ext/object/duplicable.rb +10 -8
- data/lib/active_support/core_ext/object/inclusion.rb +2 -0
- data/lib/active_support/core_ext/object/instance_variables.rb +2 -0
- data/lib/active_support/core_ext/object/json.rb +8 -0
- data/lib/active_support/core_ext/object/to_param.rb +2 -0
- data/lib/active_support/core_ext/object/to_query.rb +4 -5
- data/lib/active_support/core_ext/object/try.rb +2 -0
- data/lib/active_support/core_ext/object/with_options.rb +3 -1
- data/lib/active_support/core_ext/range.rb +3 -0
- data/lib/active_support/core_ext/range/conversions.rb +9 -1
- data/lib/active_support/core_ext/range/each.rb +5 -1
- data/lib/active_support/core_ext/range/include_range.rb +2 -0
- data/lib/active_support/core_ext/range/include_time_with_zone.rb +23 -0
- data/lib/active_support/core_ext/range/overlaps.rb +2 -0
- data/lib/active_support/core_ext/regexp.rb +2 -0
- data/lib/active_support/core_ext/securerandom.rb +2 -0
- data/lib/active_support/core_ext/string.rb +2 -0
- data/lib/active_support/core_ext/string/access.rb +2 -0
- data/lib/active_support/core_ext/string/behavior.rb +2 -0
- data/lib/active_support/core_ext/string/conversions.rb +2 -0
- data/lib/active_support/core_ext/string/exclude.rb +2 -0
- data/lib/active_support/core_ext/string/filters.rb +2 -0
- data/lib/active_support/core_ext/string/indent.rb +2 -0
- data/lib/active_support/core_ext/string/inflections.rb +26 -12
- data/lib/active_support/core_ext/string/inquiry.rb +2 -0
- data/lib/active_support/core_ext/string/multibyte.rb +2 -0
- data/lib/active_support/core_ext/string/output_safety.rb +6 -7
- data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -0
- data/lib/active_support/core_ext/string/strip.rb +2 -0
- data/lib/active_support/core_ext/string/zones.rb +2 -0
- data/lib/active_support/core_ext/time.rb +2 -0
- data/lib/active_support/core_ext/time/acts_like.rb +2 -0
- data/lib/active_support/core_ext/time/calculations.rb +23 -15
- data/lib/active_support/core_ext/time/compatibility.rb +4 -2
- data/lib/active_support/core_ext/time/conversions.rb +2 -0
- data/lib/active_support/core_ext/time/zones.rb +6 -4
- data/lib/active_support/core_ext/uri.rb +4 -1
- data/lib/active_support/current_attributes.rb +195 -0
- data/lib/active_support/dependencies.rb +15 -25
- data/lib/active_support/dependencies/autoload.rb +2 -0
- data/lib/active_support/dependencies/interlock.rb +2 -0
- data/lib/active_support/deprecation.rb +4 -2
- data/lib/active_support/deprecation/behaviors.rb +23 -8
- data/lib/active_support/deprecation/constant_accessor.rb +3 -1
- data/lib/active_support/deprecation/instance_delegator.rb +2 -0
- data/lib/active_support/deprecation/method_wrappers.rb +2 -7
- data/lib/active_support/deprecation/proxy_wrappers.rb +4 -1
- data/lib/active_support/deprecation/reporting.rb +4 -2
- data/lib/active_support/descendants_tracker.rb +2 -0
- data/lib/active_support/duration.rb +8 -14
- data/lib/active_support/duration/iso8601_parser.rb +4 -2
- data/lib/active_support/duration/iso8601_serializer.rb +4 -2
- data/lib/active_support/encrypted_configuration.rb +48 -0
- data/lib/active_support/encrypted_file.rb +99 -0
- data/lib/active_support/evented_file_update_checker.rb +2 -0
- data/lib/active_support/execution_wrapper.rb +2 -0
- data/lib/active_support/executor.rb +2 -0
- data/lib/active_support/file_update_checker.rb +2 -0
- data/lib/active_support/gem_version.rb +5 -3
- data/lib/active_support/gzip.rb +2 -0
- data/lib/active_support/hash_with_indifferent_access.rb +33 -1
- data/lib/active_support/i18n.rb +3 -1
- data/lib/active_support/i18n_railtie.rb +5 -11
- data/lib/active_support/inflections.rb +2 -0
- data/lib/active_support/inflector.rb +2 -0
- data/lib/active_support/inflector/inflections.rb +19 -3
- data/lib/active_support/inflector/methods.rb +40 -23
- data/lib/active_support/inflector/transliterate.rb +17 -8
- data/lib/active_support/json.rb +2 -0
- data/lib/active_support/json/decoding.rb +2 -0
- data/lib/active_support/json/encoding.rb +2 -0
- data/lib/active_support/key_generator.rb +3 -1
- data/lib/active_support/lazy_load_hooks.rb +2 -0
- data/lib/active_support/log_subscriber.rb +3 -2
- data/lib/active_support/log_subscriber/test_helper.rb +2 -0
- data/lib/active_support/logger.rb +2 -0
- data/lib/active_support/logger_silence.rb +3 -2
- data/lib/active_support/logger_thread_safe_level.rb +2 -0
- data/lib/active_support/message_encryptor.rb +94 -22
- data/lib/active_support/message_verifier.rb +78 -7
- data/lib/active_support/messages/metadata.rb +71 -0
- data/lib/active_support/messages/rotation_configuration.rb +22 -0
- data/lib/active_support/messages/rotator.rb +56 -0
- data/lib/active_support/multibyte.rb +2 -0
- data/lib/active_support/multibyte/chars.rb +2 -0
- data/lib/active_support/multibyte/unicode.rb +3 -1
- data/lib/active_support/notifications.rb +2 -0
- data/lib/active_support/notifications/fanout.rb +2 -0
- data/lib/active_support/notifications/instrumenter.rb +2 -0
- data/lib/active_support/number_helper.rb +2 -0
- data/lib/active_support/number_helper/number_converter.rb +2 -0
- data/lib/active_support/number_helper/number_to_currency_converter.rb +2 -0
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +2 -0
- data/lib/active_support/number_helper/number_to_human_converter.rb +2 -0
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +2 -0
- data/lib/active_support/number_helper/number_to_percentage_converter.rb +2 -0
- data/lib/active_support/number_helper/number_to_phone_converter.rb +3 -1
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +2 -20
- data/lib/active_support/number_helper/rounding_helper.rb +5 -3
- data/lib/active_support/option_merger.rb +2 -0
- data/lib/active_support/ordered_hash.rb +2 -0
- data/lib/active_support/ordered_options.rb +4 -2
- data/lib/active_support/per_thread_registry.rb +2 -0
- data/lib/active_support/proxy_object.rb +2 -0
- data/lib/active_support/rails.rb +2 -0
- data/lib/active_support/railtie.rb +27 -8
- data/lib/active_support/reloader.rb +7 -5
- data/lib/active_support/rescuable.rb +3 -2
- data/lib/active_support/security_utils.rb +15 -11
- data/lib/active_support/string_inquirer.rb +2 -0
- data/lib/active_support/subscriber.rb +2 -0
- data/lib/active_support/tagged_logging.rb +2 -0
- data/lib/active_support/test_case.rb +2 -1
- data/lib/active_support/testing/assertions.rb +6 -4
- data/lib/active_support/testing/autorun.rb +2 -0
- data/lib/active_support/testing/constant_lookup.rb +2 -0
- data/lib/active_support/testing/declarative.rb +2 -0
- data/lib/active_support/testing/deprecation.rb +2 -0
- data/lib/active_support/testing/file_fixtures.rb +2 -0
- data/lib/active_support/testing/isolation.rb +5 -5
- data/lib/active_support/testing/method_call_assertions.rb +2 -0
- data/lib/active_support/testing/setup_and_teardown.rb +2 -0
- data/lib/active_support/testing/stream.rb +2 -0
- data/lib/active_support/testing/tagged_logging.rb +2 -0
- data/lib/active_support/testing/time_helpers.rb +31 -2
- data/lib/active_support/time.rb +2 -0
- data/lib/active_support/time_with_zone.rb +38 -0
- data/lib/active_support/values/time_zone.rb +20 -12
- data/lib/active_support/version.rb +2 -0
- data/lib/active_support/xml_mini.rb +2 -0
- data/lib/active_support/xml_mini/jdom.rb +4 -2
- data/lib/active_support/xml_mini/libxml.rb +3 -1
- data/lib/active_support/xml_mini/libxmlsax.rb +4 -2
- data/lib/active_support/xml_mini/nokogiri.rb +3 -1
- data/lib/active_support/xml_mini/nokogirisax.rb +3 -1
- data/lib/active_support/xml_mini/rexml.rb +3 -1
- metadata +19 -15
@@ -1,5 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "erb"
|
2
4
|
require "active_support/core_ext/kernel/singleton_class"
|
5
|
+
require "active_support/core_ext/module/redefine_method"
|
3
6
|
require "active_support/multibyte/unicode"
|
4
7
|
|
5
8
|
class ERB
|
@@ -12,22 +15,18 @@ class ERB
|
|
12
15
|
# A utility method for escaping HTML tag characters.
|
13
16
|
# This method is also aliased as <tt>h</tt>.
|
14
17
|
#
|
15
|
-
# In your ERB templates, use this method to escape any unsafe content. For example:
|
16
|
-
# <%= h @person.name %>
|
17
|
-
#
|
18
18
|
# puts html_escape('is a > 0 & a < 10?')
|
19
19
|
# # => is a > 0 & a < 10?
|
20
20
|
def html_escape(s)
|
21
21
|
unwrapped_html_escape(s).html_safe
|
22
22
|
end
|
23
23
|
|
24
|
-
|
25
|
-
remove_method(:h)
|
24
|
+
silence_redefinition_of_method :h
|
26
25
|
alias h html_escape
|
27
26
|
|
28
27
|
module_function :h
|
29
28
|
|
30
|
-
singleton_class.
|
29
|
+
singleton_class.silence_redefinition_of_method :html_escape
|
31
30
|
module_function :html_escape
|
32
31
|
|
33
32
|
# HTML escapes strings but doesn't wrap them with an ActiveSupport::SafeBuffer.
|
@@ -251,7 +250,7 @@ class String
|
|
251
250
|
# Marks a string as trusted safe. It will be inserted into HTML with no
|
252
251
|
# additional escaping performed. It is your responsibility to ensure that the
|
253
252
|
# string contains no malicious content. This method is equivalent to the
|
254
|
-
#
|
253
|
+
# +raw+ helper in views. It is recommended that you use +sanitize+ instead of
|
255
254
|
# this method. It should never be called on user input.
|
256
255
|
def html_safe
|
257
256
|
ActiveSupport::SafeBuffer.new(self)
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "active_support/duration"
|
2
4
|
require "active_support/core_ext/time/conversions"
|
3
5
|
require "active_support/time_with_zone"
|
@@ -107,21 +109,22 @@ class Time
|
|
107
109
|
# to the +options+ parameter. The time options (<tt>:hour</tt>, <tt>:min</tt>,
|
108
110
|
# <tt>:sec</tt>, <tt>:usec</tt>, <tt>:nsec</tt>) reset cascadingly, so if only
|
109
111
|
# the hour is passed, then minute, sec, usec and nsec is set to 0. If the hour
|
110
|
-
# and minute is passed, then sec, usec and nsec is set to 0. The +options+
|
111
|
-
#
|
112
|
-
# <tt>:
|
113
|
-
# <tt>:
|
112
|
+
# and minute is passed, then sec, usec and nsec is set to 0. The +options+ parameter
|
113
|
+
# takes a hash with any of these keys: <tt>:year</tt>, <tt>:month</tt>, <tt>:day</tt>,
|
114
|
+
# <tt>:hour</tt>, <tt>:min</tt>, <tt>:sec</tt>, <tt>:usec</tt>, <tt>:nsec</tt>,
|
115
|
+
# <tt>:offset</tt>. Pass either <tt>:usec</tt> or <tt>:nsec</tt>, not both.
|
114
116
|
#
|
115
117
|
# Time.new(2012, 8, 29, 22, 35, 0).change(day: 1) # => Time.new(2012, 8, 1, 22, 35, 0)
|
116
118
|
# Time.new(2012, 8, 29, 22, 35, 0).change(year: 1981, day: 1) # => Time.new(1981, 8, 1, 22, 35, 0)
|
117
119
|
# Time.new(2012, 8, 29, 22, 35, 0).change(year: 1981, hour: 0) # => Time.new(1981, 8, 29, 0, 0, 0)
|
118
120
|
def change(options)
|
119
|
-
new_year
|
120
|
-
new_month
|
121
|
-
new_day
|
122
|
-
new_hour
|
123
|
-
new_min
|
124
|
-
new_sec
|
121
|
+
new_year = options.fetch(:year, year)
|
122
|
+
new_month = options.fetch(:month, month)
|
123
|
+
new_day = options.fetch(:day, day)
|
124
|
+
new_hour = options.fetch(:hour, hour)
|
125
|
+
new_min = options.fetch(:min, options[:hour] ? 0 : min)
|
126
|
+
new_sec = options.fetch(:sec, (options[:hour] || options[:min]) ? 0 : sec)
|
127
|
+
new_offset = options.fetch(:offset, nil)
|
125
128
|
|
126
129
|
if new_nsec = options[:nsec]
|
127
130
|
raise ArgumentError, "Can't change both :nsec and :usec at the same time: #{options.inspect}" if options[:usec]
|
@@ -130,13 +133,18 @@ class Time
|
|
130
133
|
new_usec = options.fetch(:usec, (options[:hour] || options[:min] || options[:sec]) ? 0 : Rational(nsec, 1000))
|
131
134
|
end
|
132
135
|
|
133
|
-
if
|
134
|
-
|
136
|
+
raise ArgumentError, "argument out of range" if new_usec >= 1000000
|
137
|
+
|
138
|
+
new_sec += Rational(new_usec, 1000000)
|
139
|
+
|
140
|
+
if new_offset
|
141
|
+
::Time.new(new_year, new_month, new_day, new_hour, new_min, new_sec, new_offset)
|
142
|
+
elsif utc?
|
143
|
+
::Time.utc(new_year, new_month, new_day, new_hour, new_min, new_sec)
|
135
144
|
elsif zone
|
136
|
-
::Time.local(new_year, new_month, new_day, new_hour, new_min, new_sec
|
145
|
+
::Time.local(new_year, new_month, new_day, new_hour, new_min, new_sec)
|
137
146
|
else
|
138
|
-
|
139
|
-
::Time.new(new_year, new_month, new_day, new_hour, new_min, new_sec + (new_usec.to_r / 1000000), utc_offset)
|
147
|
+
::Time.new(new_year, new_month, new_day, new_hour, new_min, new_sec, utc_offset)
|
140
148
|
end
|
141
149
|
end
|
142
150
|
|
@@ -1,10 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "active_support/core_ext/date_and_time/compatibility"
|
2
|
-
require "active_support/core_ext/module/
|
4
|
+
require "active_support/core_ext/module/redefine_method"
|
3
5
|
|
4
6
|
class Time
|
5
7
|
include DateAndTime::Compatibility
|
6
8
|
|
7
|
-
|
9
|
+
silence_redefinition_of_method :to_time
|
8
10
|
|
9
11
|
# Either return +self+ or the time in the local system timezone depending
|
10
12
|
# on the setting of +ActiveSupport.to_time_preserves_timezone+.
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "active_support/time_with_zone"
|
2
4
|
require "active_support/core_ext/time/acts_like"
|
3
5
|
require "active_support/core_ext/date_and_time/zones"
|
@@ -53,10 +55,10 @@ class Time
|
|
53
55
|
# end
|
54
56
|
# end
|
55
57
|
#
|
56
|
-
#
|
57
|
-
#
|
58
|
-
#
|
59
|
-
#
|
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.
|
60
62
|
def use_zone(time_zone)
|
61
63
|
new_zone = find_zone!(time_zone)
|
62
64
|
begin
|
@@ -1,10 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "uri"
|
2
4
|
str = "\xE6\x97\xA5\xE6\x9C\xAC\xE8\xAA\x9E" # Ni-ho-nn-go in UTF-8, means Japanese.
|
3
5
|
parser = URI::Parser.new
|
4
6
|
|
5
7
|
unless str == parser.unescape(parser.escape(str))
|
8
|
+
require "active_support/core_ext/module/redefine_method"
|
6
9
|
URI::Parser.class_eval do
|
7
|
-
|
10
|
+
silence_redefinition_of_method :unescape
|
8
11
|
def unescape(str, escaped = /%[a-fA-F\d]{2}/)
|
9
12
|
# TODO: Are we actually sure that ASCII == UTF-8?
|
10
13
|
# YK: My initial experiments say yes, but let's be sure please
|
@@ -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 "set"
|
2
4
|
require "thread"
|
3
5
|
require "concurrent/map"
|
@@ -18,8 +20,7 @@ module ActiveSupport #:nodoc:
|
|
18
20
|
module Dependencies #:nodoc:
|
19
21
|
extend self
|
20
22
|
|
21
|
-
mattr_accessor :interlock
|
22
|
-
self.interlock = Interlock.new
|
23
|
+
mattr_accessor :interlock, default: Interlock.new
|
23
24
|
|
24
25
|
# :doc:
|
25
26
|
|
@@ -46,46 +47,37 @@ module ActiveSupport #:nodoc:
|
|
46
47
|
# :nodoc:
|
47
48
|
|
48
49
|
# Should we turn on Ruby warnings on the first load of dependent files?
|
49
|
-
mattr_accessor :warnings_on_first_load
|
50
|
-
self.warnings_on_first_load = false
|
50
|
+
mattr_accessor :warnings_on_first_load, default: false
|
51
51
|
|
52
52
|
# All files ever loaded.
|
53
|
-
mattr_accessor :history
|
54
|
-
self.history = Set.new
|
53
|
+
mattr_accessor :history, default: Set.new
|
55
54
|
|
56
55
|
# All files currently loaded.
|
57
|
-
mattr_accessor :loaded
|
58
|
-
self.loaded = Set.new
|
56
|
+
mattr_accessor :loaded, default: Set.new
|
59
57
|
|
60
58
|
# Stack of files being loaded.
|
61
|
-
mattr_accessor :loading
|
62
|
-
self.loading = []
|
59
|
+
mattr_accessor :loading, default: []
|
63
60
|
|
64
61
|
# Should we load files or require them?
|
65
|
-
mattr_accessor :mechanism
|
66
|
-
self.mechanism = ENV["NO_RELOAD"] ? :require : :load
|
62
|
+
mattr_accessor :mechanism, default: ENV["NO_RELOAD"] ? :require : :load
|
67
63
|
|
68
64
|
# The set of directories from which we may automatically load files. Files
|
69
65
|
# under these directories will be reloaded on each request in development mode,
|
70
66
|
# unless the directory also appears in autoload_once_paths.
|
71
|
-
mattr_accessor :autoload_paths
|
72
|
-
self.autoload_paths = []
|
67
|
+
mattr_accessor :autoload_paths, default: []
|
73
68
|
|
74
69
|
# The set of directories from which automatically loaded constants are loaded
|
75
70
|
# only once. All directories in this set must also be present in +autoload_paths+.
|
76
|
-
mattr_accessor :autoload_once_paths
|
77
|
-
self.autoload_once_paths = []
|
71
|
+
mattr_accessor :autoload_once_paths, default: []
|
78
72
|
|
79
73
|
# An array of qualified constant names that have been loaded. Adding a name
|
80
74
|
# to this array will cause it to be unloaded the next time Dependencies are
|
81
75
|
# cleared.
|
82
|
-
mattr_accessor :autoloaded_constants
|
83
|
-
self.autoloaded_constants = []
|
76
|
+
mattr_accessor :autoloaded_constants, default: []
|
84
77
|
|
85
78
|
# An array of constant names that need to be unloaded on every request. Used
|
86
79
|
# to allow arbitrary constants to be marked for unloading.
|
87
|
-
mattr_accessor :explicitly_unloadable_constants
|
88
|
-
self.explicitly_unloadable_constants = []
|
80
|
+
mattr_accessor :explicitly_unloadable_constants, default: []
|
89
81
|
|
90
82
|
# The WatchStack keeps a stack of the modules being watched as files are
|
91
83
|
# loaded. If a file in the process of being loaded (parent.rb) triggers the
|
@@ -93,7 +85,7 @@ module ActiveSupport #:nodoc:
|
|
93
85
|
# handles the new constants.
|
94
86
|
#
|
95
87
|
# If child.rb is being autoloaded, its constants will be added to
|
96
|
-
# autoloaded_constants. If it was being
|
88
|
+
# autoloaded_constants. If it was being required, they will be discarded.
|
97
89
|
#
|
98
90
|
# This is handled by walking back up the watch stack and adding the constants
|
99
91
|
# found by child.rb to the list of original constants in parent.rb.
|
@@ -175,8 +167,7 @@ module ActiveSupport #:nodoc:
|
|
175
167
|
end
|
176
168
|
|
177
169
|
# An internal stack used to record which constants are loaded by any block.
|
178
|
-
mattr_accessor :constant_watch_stack
|
179
|
-
self.constant_watch_stack = WatchStack.new
|
170
|
+
mattr_accessor :constant_watch_stack, default: WatchStack.new
|
180
171
|
|
181
172
|
# Module includes this module.
|
182
173
|
module ModuleConstMissing #:nodoc:
|
@@ -456,7 +447,6 @@ module ActiveSupport #:nodoc:
|
|
456
447
|
mod = Module.new
|
457
448
|
into.const_set const_name, mod
|
458
449
|
autoloaded_constants << qualified_name unless autoload_once_paths.include?(base_path)
|
459
|
-
autoloaded_constants.uniq!
|
460
450
|
mod
|
461
451
|
end
|
462
452
|
|
@@ -625,7 +615,7 @@ module ActiveSupport #:nodoc:
|
|
625
615
|
return false if desc.is_a?(Module) && desc.anonymous?
|
626
616
|
name = to_constant_name desc
|
627
617
|
return false unless qualified_const_defined?(name)
|
628
|
-
|
618
|
+
autoloaded_constants.include?(name)
|
629
619
|
end
|
630
620
|
|
631
621
|
# Will the provided constant descriptor be unloaded?
|