activesupport 4.2.11.1 → 5.2.8.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activesupport might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +441 -399
- data/MIT-LICENSE +2 -2
- data/README.rdoc +4 -5
- data/lib/active_support/all.rb +5 -3
- data/lib/active_support/array_inquirer.rb +48 -0
- data/lib/active_support/backtrace_cleaner.rb +7 -5
- data/lib/active_support/benchmarkable.rb +6 -4
- data/lib/active_support/builder.rb +3 -1
- data/lib/active_support/cache/file_store.rb +41 -35
- data/lib/active_support/cache/mem_cache_store.rb +91 -91
- data/lib/active_support/cache/memory_store.rb +27 -30
- data/lib/active_support/cache/null_store.rb +7 -8
- data/lib/active_support/cache/redis_cache_store.rb +466 -0
- data/lib/active_support/cache/strategy/local_cache.rb +67 -34
- data/lib/active_support/cache/strategy/local_cache_middleware.rb +10 -9
- data/lib/active_support/cache.rb +287 -196
- data/lib/active_support/callbacks.rb +640 -590
- data/lib/active_support/concern.rb +11 -5
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +35 -0
- data/lib/active_support/concurrency/share_lock.rb +227 -0
- data/lib/active_support/configurable.rb +8 -5
- data/lib/active_support/core_ext/array/access.rb +29 -1
- data/lib/active_support/core_ext/array/conversions.rb +22 -18
- data/lib/active_support/core_ext/array/extract_options.rb +2 -0
- data/lib/active_support/core_ext/array/grouping.rb +11 -18
- data/lib/active_support/core_ext/array/inquiry.rb +19 -0
- data/lib/active_support/core_ext/array/prepend_and_append.rb +5 -3
- data/lib/active_support/core_ext/array/wrap.rb +7 -4
- data/lib/active_support/core_ext/array.rb +9 -6
- data/lib/active_support/core_ext/benchmark.rb +3 -1
- data/lib/active_support/core_ext/big_decimal/conversions.rb +10 -12
- data/lib/active_support/core_ext/big_decimal.rb +3 -1
- data/lib/active_support/core_ext/class/attribute.rb +41 -22
- data/lib/active_support/core_ext/class/attribute_accessors.rb +3 -1
- data/lib/active_support/core_ext/class/subclasses.rb +20 -6
- data/lib/active_support/core_ext/class.rb +4 -3
- data/lib/active_support/core_ext/date/acts_like.rb +3 -1
- data/lib/active_support/core_ext/date/blank.rb +14 -0
- data/lib/active_support/core_ext/date/calculations.rb +11 -9
- data/lib/active_support/core_ext/date/conversions.rb +25 -23
- data/lib/active_support/core_ext/date/zones.rb +4 -2
- data/lib/active_support/core_ext/date.rb +6 -4
- data/lib/active_support/core_ext/date_and_time/calculations.rb +170 -58
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +4 -3
- data/lib/active_support/core_ext/date_and_time/zones.rb +12 -12
- data/lib/active_support/core_ext/date_time/acts_like.rb +4 -2
- data/lib/active_support/core_ext/date_time/blank.rb +14 -0
- data/lib/active_support/core_ext/date_time/calculations.rb +36 -18
- data/lib/active_support/core_ext/date_time/compatibility.rb +8 -6
- data/lib/active_support/core_ext/date_time/conversions.rb +16 -12
- data/lib/active_support/core_ext/date_time.rb +7 -5
- data/lib/active_support/core_ext/digest/uuid.rb +7 -5
- data/lib/active_support/core_ext/digest.rb +3 -0
- data/lib/active_support/core_ext/enumerable.rb +101 -33
- data/lib/active_support/core_ext/file/atomic.rb +38 -31
- data/lib/active_support/core_ext/file.rb +3 -1
- data/lib/active_support/core_ext/hash/compact.rb +14 -9
- data/lib/active_support/core_ext/hash/conversions.rb +62 -41
- data/lib/active_support/core_ext/hash/deep_merge.rb +9 -13
- data/lib/active_support/core_ext/hash/except.rb +11 -8
- data/lib/active_support/core_ext/hash/indifferent_access.rb +4 -3
- data/lib/active_support/core_ext/hash/keys.rb +33 -27
- data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
- data/lib/active_support/core_ext/hash/slice.rb +8 -8
- data/lib/active_support/core_ext/hash/transform_values.rb +14 -5
- data/lib/active_support/core_ext/hash.rb +11 -9
- data/lib/active_support/core_ext/integer/inflections.rb +3 -1
- data/lib/active_support/core_ext/integer/multiple.rb +2 -0
- data/lib/active_support/core_ext/integer/time.rb +11 -18
- data/lib/active_support/core_ext/integer.rb +5 -3
- data/lib/active_support/core_ext/kernel/agnostics.rb +2 -0
- data/lib/active_support/core_ext/kernel/concern.rb +5 -1
- data/lib/active_support/core_ext/kernel/reporting.rb +4 -84
- data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
- data/lib/active_support/core_ext/kernel.rb +6 -5
- data/lib/active_support/core_ext/load_error.rb +3 -22
- data/lib/active_support/core_ext/marshal.rb +8 -8
- data/lib/active_support/core_ext/module/aliasing.rb +6 -44
- data/lib/active_support/core_ext/module/anonymous.rb +12 -1
- data/lib/active_support/core_ext/module/attr_internal.rb +8 -9
- data/lib/active_support/core_ext/module/attribute_accessors.rb +43 -40
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +150 -0
- data/lib/active_support/core_ext/module/concerning.rb +11 -12
- data/lib/active_support/core_ext/module/delegation.rb +99 -29
- data/lib/active_support/core_ext/module/deprecation.rb +4 -2
- data/lib/active_support/core_ext/module/introspection.rb +9 -9
- data/lib/active_support/core_ext/module/reachable.rb +5 -2
- data/lib/active_support/core_ext/module/redefine_method.rb +49 -0
- data/lib/active_support/core_ext/module/remove_method.rb +8 -3
- data/lib/active_support/core_ext/module.rb +14 -11
- data/lib/active_support/core_ext/name_error.rb +22 -2
- data/lib/active_support/core_ext/numeric/bytes.rb +22 -0
- data/lib/active_support/core_ext/numeric/conversions.rb +78 -81
- data/lib/active_support/core_ext/numeric/inquiry.rb +28 -0
- data/lib/active_support/core_ext/numeric/time.rb +35 -23
- data/lib/active_support/core_ext/numeric.rb +6 -3
- data/lib/active_support/core_ext/object/acts_like.rb +12 -1
- data/lib/active_support/core_ext/object/blank.rb +27 -2
- data/lib/active_support/core_ext/object/conversions.rb +6 -4
- data/lib/active_support/core_ext/object/deep_dup.rb +13 -4
- data/lib/active_support/core_ext/object/duplicable.rb +41 -14
- data/lib/active_support/core_ext/object/inclusion.rb +5 -3
- data/lib/active_support/core_ext/object/instance_variables.rb +3 -1
- data/lib/active_support/core_ext/object/json.rb +49 -19
- data/lib/active_support/core_ext/object/to_param.rb +3 -1
- data/lib/active_support/core_ext/object/to_query.rb +10 -5
- data/lib/active_support/core_ext/object/try.rb +69 -21
- data/lib/active_support/core_ext/object/with_options.rb +16 -3
- data/lib/active_support/core_ext/object.rb +14 -13
- data/lib/active_support/core_ext/range/compare_range.rb +61 -0
- data/lib/active_support/core_ext/range/conversions.rb +27 -7
- data/lib/active_support/core_ext/range/each.rb +19 -17
- data/lib/active_support/core_ext/range/include_range.rb +2 -22
- 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/range.rb +7 -4
- data/lib/active_support/core_ext/regexp.rb +6 -0
- data/lib/active_support/core_ext/securerandom.rb +25 -0
- data/lib/active_support/core_ext/string/access.rb +8 -6
- data/lib/active_support/core_ext/string/behavior.rb +3 -1
- data/lib/active_support/core_ext/string/conversions.rb +7 -4
- data/lib/active_support/core_ext/string/exclude.rb +2 -0
- data/lib/active_support/core_ext/string/filters.rb +6 -5
- data/lib/active_support/core_ext/string/indent.rb +6 -4
- data/lib/active_support/core_ext/string/inflections.rb +61 -24
- data/lib/active_support/core_ext/string/inquiry.rb +3 -1
- data/lib/active_support/core_ext/string/multibyte.rb +15 -7
- data/lib/active_support/core_ext/string/output_safety.rb +62 -38
- data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -0
- data/lib/active_support/core_ext/string/strip.rb +4 -5
- data/lib/active_support/core_ext/string/zones.rb +4 -2
- data/lib/active_support/core_ext/string.rb +15 -13
- data/lib/active_support/core_ext/time/acts_like.rb +3 -1
- data/lib/active_support/core_ext/time/calculations.rb +85 -51
- data/lib/active_support/core_ext/time/compatibility.rb +4 -2
- data/lib/active_support/core_ext/time/conversions.rb +20 -13
- data/lib/active_support/core_ext/time/zones.rb +41 -7
- data/lib/active_support/core_ext/time.rb +7 -6
- data/lib/active_support/core_ext/uri.rb +6 -8
- data/lib/active_support/core_ext.rb +3 -1
- data/lib/active_support/current_attributes.rb +195 -0
- data/lib/active_support/dependencies/autoload.rb +2 -0
- data/lib/active_support/dependencies/interlock.rb +57 -0
- data/lib/active_support/dependencies.rb +152 -161
- data/lib/active_support/deprecation/behaviors.rb +44 -11
- data/lib/active_support/deprecation/constant_accessor.rb +52 -0
- data/lib/active_support/deprecation/instance_delegator.rb +17 -2
- data/lib/active_support/deprecation/method_wrappers.rb +66 -20
- data/lib/active_support/deprecation/proxy_wrappers.rb +56 -28
- data/lib/active_support/deprecation/reporting.rb +32 -12
- data/lib/active_support/deprecation.rb +12 -9
- data/lib/active_support/descendants_tracker.rb +2 -0
- data/lib/active_support/digest.rb +20 -0
- data/lib/active_support/duration/iso8601_parser.rb +125 -0
- data/lib/active_support/duration/iso8601_serializer.rb +55 -0
- data/lib/active_support/duration.rb +314 -38
- data/lib/active_support/encrypted_configuration.rb +49 -0
- data/lib/active_support/encrypted_file.rb +99 -0
- data/lib/active_support/evented_file_update_checker.rb +205 -0
- data/lib/active_support/execution_wrapper.rb +131 -0
- data/lib/active_support/executor.rb +8 -0
- data/lib/active_support/file_update_checker.rb +63 -37
- data/lib/active_support/gem_version.rb +5 -3
- data/lib/active_support/gzip.rb +7 -5
- data/lib/active_support/hash_with_indifferent_access.rb +123 -28
- data/lib/active_support/i18n.rb +8 -6
- data/lib/active_support/i18n_railtie.rb +37 -13
- data/lib/active_support/inflections.rb +13 -11
- data/lib/active_support/inflector/inflections.rb +61 -12
- data/lib/active_support/inflector/methods.rb +163 -136
- data/lib/active_support/inflector/transliterate.rb +48 -27
- data/lib/active_support/inflector.rb +7 -5
- data/lib/active_support/json/decoding.rb +16 -13
- data/lib/active_support/json/encoding.rb +11 -58
- data/lib/active_support/json.rb +4 -2
- data/lib/active_support/key_generator.rb +25 -25
- data/lib/active_support/lazy_load_hooks.rb +50 -20
- data/lib/active_support/locale/en.yml +2 -0
- data/lib/active_support/log_subscriber/test_helper.rb +14 -12
- data/lib/active_support/log_subscriber.rb +13 -10
- data/lib/active_support/logger.rb +8 -7
- data/lib/active_support/logger_silence.rb +6 -4
- data/lib/active_support/logger_thread_safe_level.rb +7 -5
- data/lib/active_support/message_encryptor.rb +168 -53
- data/lib/active_support/message_verifier.rb +150 -17
- 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/chars.rb +36 -23
- data/lib/active_support/multibyte/unicode.rb +100 -96
- data/lib/active_support/multibyte.rb +4 -2
- data/lib/active_support/notifications/fanout.rb +11 -9
- data/lib/active_support/notifications/instrumenter.rb +27 -7
- data/lib/active_support/notifications.rb +11 -7
- data/lib/active_support/number_helper/number_converter.rb +13 -11
- data/lib/active_support/number_helper/number_to_currency_converter.rb +9 -9
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +9 -3
- data/lib/active_support/number_helper/number_to_human_converter.rb +11 -9
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +9 -8
- data/lib/active_support/number_helper/number_to_percentage_converter.rb +3 -1
- data/lib/active_support/number_helper/number_to_phone_converter.rb +13 -4
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +23 -56
- data/lib/active_support/number_helper/rounding_helper.rb +66 -0
- data/lib/active_support/number_helper.rb +94 -68
- data/lib/active_support/option_merger.rb +3 -1
- data/lib/active_support/ordered_hash.rb +6 -4
- data/lib/active_support/ordered_options.rb +23 -5
- data/lib/active_support/per_thread_registry.rb +9 -4
- data/lib/active_support/proxy_object.rb +2 -0
- data/lib/active_support/rails.rb +16 -8
- data/lib/active_support/railtie.rb +43 -9
- data/lib/active_support/reloader.rb +131 -0
- data/lib/active_support/rescuable.rb +108 -53
- data/lib/active_support/security_utils.rb +15 -11
- data/lib/active_support/string_inquirer.rb +11 -3
- data/lib/active_support/subscriber.rb +21 -16
- data/lib/active_support/tagged_logging.rb +14 -11
- data/lib/active_support/test_case.rb +19 -47
- data/lib/active_support/testing/assertions.rb +137 -20
- data/lib/active_support/testing/autorun.rb +4 -2
- data/lib/active_support/testing/constant_lookup.rb +2 -1
- data/lib/active_support/testing/declarative.rb +3 -1
- data/lib/active_support/testing/deprecation.rb +14 -10
- data/lib/active_support/testing/file_fixtures.rb +36 -0
- data/lib/active_support/testing/isolation.rb +34 -25
- data/lib/active_support/testing/method_call_assertions.rb +43 -0
- data/lib/active_support/testing/setup_and_teardown.rb +13 -8
- data/lib/active_support/testing/stream.rb +44 -0
- data/lib/active_support/testing/tagged_logging.rb +3 -1
- data/lib/active_support/testing/time_helpers.rb +81 -15
- data/lib/active_support/time.rb +14 -12
- data/lib/active_support/time_with_zone.rb +169 -39
- data/lib/active_support/values/time_zone.rb +196 -61
- data/lib/active_support/values/unicode_tables.dat +0 -0
- data/lib/active_support/version.rb +3 -1
- data/lib/active_support/xml_mini/jdom.rb +116 -114
- data/lib/active_support/xml_mini/libxml.rb +16 -13
- data/lib/active_support/xml_mini/libxmlsax.rb +15 -14
- data/lib/active_support/xml_mini/nokogiri.rb +14 -12
- data/lib/active_support/xml_mini/nokogirisax.rb +14 -13
- data/lib/active_support/xml_mini/rexml.rb +11 -9
- data/lib/active_support/xml_mini.rb +37 -37
- data/lib/active_support.rb +12 -11
- metadata +57 -27
- data/lib/active_support/concurrency/latch.rb +0 -27
- data/lib/active_support/core_ext/big_decimal/yaml_conversions.rb +0 -16
- data/lib/active_support/core_ext/class/delegating_attributes.rb +0 -45
- data/lib/active_support/core_ext/date_time/zones.rb +0 -6
- data/lib/active_support/core_ext/kernel/debugger.rb +0 -10
- data/lib/active_support/core_ext/module/method_transplanting.rb +0 -13
- data/lib/active_support/core_ext/module/qualified_const.rb +0 -52
- data/lib/active_support/core_ext/object/itself.rb +0 -15
- data/lib/active_support/core_ext/struct.rb +0 -6
- data/lib/active_support/core_ext/thread.rb +0 -86
- data/lib/active_support/core_ext/time/marshal.rb +0 -30
@@ -1,6 +1,8 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/time_with_zone"
|
4
|
+
require "active_support/core_ext/time/acts_like"
|
5
|
+
require "active_support/core_ext/date_and_time/zones"
|
4
6
|
|
5
7
|
class Time
|
6
8
|
include DateAndTime::Zones
|
@@ -26,7 +28,7 @@ class Time
|
|
26
28
|
# <tt>current_user.time_zone</tt> just needs to return a string identifying the user's preferred time zone:
|
27
29
|
#
|
28
30
|
# class ApplicationController < ActionController::Base
|
29
|
-
#
|
31
|
+
# around_action :set_time_zone
|
30
32
|
#
|
31
33
|
# def set_time_zone
|
32
34
|
# if logged_in?
|
@@ -40,7 +42,23 @@ class Time
|
|
40
42
|
Thread.current[:time_zone] = find_zone!(time_zone)
|
41
43
|
end
|
42
44
|
|
43
|
-
# Allows override of <tt>Time.zone</tt> locally inside supplied block;
|
45
|
+
# Allows override of <tt>Time.zone</tt> locally inside supplied block;
|
46
|
+
# resets <tt>Time.zone</tt> to existing value when done.
|
47
|
+
#
|
48
|
+
# class ApplicationController < ActionController::Base
|
49
|
+
# around_action :set_time_zone
|
50
|
+
#
|
51
|
+
# private
|
52
|
+
#
|
53
|
+
# def set_time_zone
|
54
|
+
# Time.use_zone(current_user.timezone) { yield }
|
55
|
+
# end
|
56
|
+
# end
|
57
|
+
#
|
58
|
+
# NOTE: This won't affect any <tt>ActiveSupport::TimeWithZone</tt>
|
59
|
+
# objects that have already been created, e.g. any model timestamp
|
60
|
+
# attributes that have been read before the block will remain in
|
61
|
+
# the application's default timezone.
|
44
62
|
def use_zone(time_zone)
|
45
63
|
new_zone = find_zone!(time_zone)
|
46
64
|
begin
|
@@ -51,12 +69,22 @@ class Time
|
|
51
69
|
end
|
52
70
|
end
|
53
71
|
|
54
|
-
# Returns a TimeZone instance
|
72
|
+
# Returns a TimeZone instance matching the time zone provided.
|
73
|
+
# Accepts the time zone in any format supported by <tt>Time.zone=</tt>.
|
74
|
+
# Raises an +ArgumentError+ for invalid time zones.
|
75
|
+
#
|
76
|
+
# Time.find_zone! "America/New_York" # => #<ActiveSupport::TimeZone @name="America/New_York" ...>
|
77
|
+
# Time.find_zone! "EST" # => #<ActiveSupport::TimeZone @name="EST" ...>
|
78
|
+
# Time.find_zone! -5.hours # => #<ActiveSupport::TimeZone @name="Bogota" ...>
|
79
|
+
# Time.find_zone! nil # => nil
|
80
|
+
# Time.find_zone! false # => false
|
81
|
+
# Time.find_zone! "NOT-A-TIMEZONE" # => ArgumentError: Invalid Timezone: NOT-A-TIMEZONE
|
55
82
|
def find_zone!(time_zone)
|
56
83
|
if !time_zone || time_zone.is_a?(ActiveSupport::TimeZone)
|
57
84
|
time_zone
|
58
85
|
else
|
59
|
-
#
|
86
|
+
# Look up the timezone based on the identifier (unless we've been
|
87
|
+
# passed a TZInfo::Timezone)
|
60
88
|
unless time_zone.respond_to?(:period_for_local)
|
61
89
|
time_zone = ActiveSupport::TimeZone[time_zone] || TZInfo::Timezone.get(time_zone)
|
62
90
|
end
|
@@ -72,6 +100,12 @@ class Time
|
|
72
100
|
raise ArgumentError, "Invalid Timezone: #{time_zone}"
|
73
101
|
end
|
74
102
|
|
103
|
+
# Returns a TimeZone instance matching the time zone provided.
|
104
|
+
# Accepts the time zone in any format supported by <tt>Time.zone=</tt>.
|
105
|
+
# Returns +nil+ for invalid time zones.
|
106
|
+
#
|
107
|
+
# Time.find_zone "America/New_York" # => #<ActiveSupport::TimeZone @name="America/New_York" ...>
|
108
|
+
# Time.find_zone "NOT-A-TIMEZONE" # => nil
|
75
109
|
def find_zone(time_zone)
|
76
110
|
find_zone!(time_zone) rescue nil
|
77
111
|
end
|
@@ -1,6 +1,7 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/core_ext/time/acts_like"
|
4
|
+
require "active_support/core_ext/time/calculations"
|
5
|
+
require "active_support/core_ext/time/compatibility"
|
6
|
+
require "active_support/core_ext/time/conversions"
|
7
|
+
require "active_support/core_ext/time/zones"
|
@@ -1,18 +1,16 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
unless str == parser.unescape(parser.escape(str))
|
3
|
+
require "uri"
|
4
|
+
if RUBY_VERSION < "2.6.0"
|
5
|
+
require "active_support/core_ext/module/redefine_method"
|
8
6
|
URI::Parser.class_eval do
|
9
|
-
|
7
|
+
silence_redefinition_of_method :unescape
|
10
8
|
def unescape(str, escaped = /%[a-fA-F\d]{2}/)
|
11
9
|
# TODO: Are we actually sure that ASCII == UTF-8?
|
12
10
|
# YK: My initial experiments say yes, but let's be sure please
|
13
11
|
enc = str.encoding
|
14
12
|
enc = Encoding::UTF_8 if enc == Encoding::US_ASCII
|
15
|
-
str.gsub(escaped) { [
|
13
|
+
str.dup.force_encoding(Encoding::ASCII_8BIT).gsub(escaped) { |match| [match[1, 2].hex].pack("C") }.force_encoding(enc)
|
16
14
|
end
|
17
15
|
end
|
18
16
|
end
|
@@ -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
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/concurrency/share_lock"
|
4
|
+
|
5
|
+
module ActiveSupport #:nodoc:
|
6
|
+
module Dependencies #:nodoc:
|
7
|
+
class Interlock
|
8
|
+
def initialize # :nodoc:
|
9
|
+
@lock = ActiveSupport::Concurrency::ShareLock.new
|
10
|
+
end
|
11
|
+
|
12
|
+
def loading
|
13
|
+
@lock.exclusive(purpose: :load, compatible: [:load], after_compatible: [:load]) do
|
14
|
+
yield
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def unloading
|
19
|
+
@lock.exclusive(purpose: :unload, compatible: [:load, :unload], after_compatible: [:load, :unload]) do
|
20
|
+
yield
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def start_unloading
|
25
|
+
@lock.start_exclusive(purpose: :unload, compatible: [:load, :unload])
|
26
|
+
end
|
27
|
+
|
28
|
+
def done_unloading
|
29
|
+
@lock.stop_exclusive(compatible: [:load, :unload])
|
30
|
+
end
|
31
|
+
|
32
|
+
def start_running
|
33
|
+
@lock.start_sharing
|
34
|
+
end
|
35
|
+
|
36
|
+
def done_running
|
37
|
+
@lock.stop_sharing
|
38
|
+
end
|
39
|
+
|
40
|
+
def running
|
41
|
+
@lock.sharing do
|
42
|
+
yield
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def permit_concurrent_loads
|
47
|
+
@lock.yield_shares(compatible: [:load]) do
|
48
|
+
yield
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def raw_state(&block) # :nodoc:
|
53
|
+
@lock.raw_state(&block)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|