activesupport 4.2.0 → 5.2.0
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 +366 -232
- data/MIT-LICENSE +2 -2
- data/README.rdoc +4 -5
- data/lib/active_support.rb +17 -7
- 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.rb +271 -177
- data/lib/active_support/cache/file_store.rb +41 -35
- data/lib/active_support/cache/mem_cache_store.rb +97 -88
- 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 +454 -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/callbacks.rb +654 -560
- data/lib/active_support/concern.rb +5 -3
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +17 -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.rb +3 -1
- data/lib/active_support/core_ext/array.rb +9 -6
- 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/benchmark.rb +3 -1
- data/lib/active_support/core_ext/big_decimal.rb +3 -1
- data/lib/active_support/core_ext/big_decimal/conversions.rb +10 -12
- data/lib/active_support/core_ext/class.rb +4 -3
- 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 -8
- data/lib/active_support/core_ext/date.rb +6 -4
- 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 +31 -23
- data/lib/active_support/core_ext/date/zones.rb +4 -2
- data/lib/active_support/core_ext/date_and_time/calculations.rb +179 -56
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +16 -0
- data/lib/active_support/core_ext/date_and_time/zones.rb +12 -12
- data/lib/active_support/core_ext/date_time.rb +7 -4
- 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 +58 -20
- data/lib/active_support/core_ext/date_time/compatibility.rb +18 -0
- data/lib/active_support/core_ext/date_time/conversions.rb +16 -12
- data/lib/active_support/core_ext/digest/uuid.rb +7 -5
- data/lib/active_support/core_ext/enumerable.rb +107 -28
- data/lib/active_support/core_ext/file.rb +3 -1
- data/lib/active_support/core_ext/file/atomic.rb +38 -31
- data/lib/active_support/core_ext/hash.rb +11 -9
- data/lib/active_support/core_ext/hash/compact.rb +24 -15
- data/lib/active_support/core_ext/hash/conversions.rb +63 -43
- 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 +16 -7
- data/lib/active_support/core_ext/integer.rb +5 -3
- 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 -33
- data/lib/active_support/core_ext/kernel.rb +6 -5
- 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 -83
- data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
- data/lib/active_support/core_ext/load_error.rb +3 -22
- data/lib/active_support/core_ext/marshal.rb +13 -10
- data/lib/active_support/core_ext/module.rb +14 -11
- 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 +121 -39
- 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/name_error.rb +22 -2
- data/lib/active_support/core_ext/numeric.rb +6 -3
- data/lib/active_support/core_ext/numeric/bytes.rb +22 -0
- data/lib/active_support/core_ext/numeric/conversions.rb +79 -74
- data/lib/active_support/core_ext/numeric/inquiry.rb +28 -0
- data/lib/active_support/core_ext/numeric/time.rb +35 -38
- data/lib/active_support/core_ext/object.rb +14 -13
- data/lib/active_support/core_ext/object/acts_like.rb +12 -1
- data/lib/active_support/core_ext/object/blank.rb +29 -4
- 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 +98 -45
- 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 +6 -4
- data/lib/active_support/core_ext/object/try.rb +70 -22
- data/lib/active_support/core_ext/object/with_options.rb +16 -3
- data/lib/active_support/core_ext/range.rb +7 -4
- 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 +21 -19
- 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 +6 -0
- data/lib/active_support/core_ext/securerandom.rb +25 -0
- data/lib/active_support/core_ext/string.rb +15 -13
- data/lib/active_support/core_ext/string/access.rb +9 -7
- data/lib/active_support/core_ext/string/behavior.rb +3 -1
- data/lib/active_support/core_ext/string/conversions.rb +8 -5
- data/lib/active_support/core_ext/string/exclude.rb +2 -0
- data/lib/active_support/core_ext/string/filters.rb +10 -8
- 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 +35 -35
- 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/time.rb +7 -5
- data/lib/active_support/core_ext/time/acts_like.rb +3 -1
- data/lib/active_support/core_ext/time/calculations.rb +101 -51
- data/lib/active_support/core_ext/time/compatibility.rb +16 -0
- 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/uri.rb +5 -4
- data/lib/active_support/current_attributes.rb +195 -0
- data/lib/active_support/dependencies.rb +143 -160
- data/lib/active_support/dependencies/autoload.rb +2 -0
- data/lib/active_support/dependencies/interlock.rb +57 -0
- data/lib/active_support/deprecation.rb +12 -9
- data/lib/active_support/deprecation/behaviors.rb +41 -12
- 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 +54 -21
- data/lib/active_support/deprecation/proxy_wrappers.rb +56 -28
- data/lib/active_support/deprecation/reporting.rb +32 -12
- data/lib/active_support/descendants_tracker.rb +2 -0
- data/lib/active_support/digest.rb +20 -0
- data/lib/active_support/duration.rb +326 -30
- data/lib/active_support/duration/iso8601_parser.rb +125 -0
- data/lib/active_support/duration/iso8601_serializer.rb +55 -0
- 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 +128 -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 +4 -2
- data/lib/active_support/gzip.rb +7 -5
- data/lib/active_support/hash_with_indifferent_access.rb +130 -30
- data/lib/active_support/i18n.rb +8 -6
- data/lib/active_support/i18n_railtie.rb +34 -14
- data/lib/active_support/inflections.rb +13 -11
- data/lib/active_support/inflector.rb +7 -5
- data/lib/active_support/inflector/inflections.rb +61 -12
- data/lib/active_support/inflector/methods.rb +161 -136
- data/lib/active_support/inflector/transliterate.rb +48 -27
- data/lib/active_support/json.rb +4 -2
- data/lib/active_support/json/decoding.rb +16 -13
- data/lib/active_support/json/encoding.rb +15 -57
- 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.rb +13 -10
- data/lib/active_support/log_subscriber/test_helper.rb +14 -12
- data/lib/active_support/logger.rb +54 -3
- data/lib/active_support/logger_silence.rb +12 -7
- data/lib/active_support/logger_thread_safe_level.rb +33 -0
- data/lib/active_support/message_encryptor.rb +173 -51
- 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.rb +4 -2
- data/lib/active_support/multibyte/chars.rb +37 -24
- data/lib/active_support/multibyte/unicode.rb +100 -96
- data/lib/active_support/notifications.rb +11 -7
- data/lib/active_support/notifications/fanout.rb +10 -8
- data/lib/active_support/notifications/instrumenter.rb +27 -7
- data/lib/active_support/number_helper.rb +94 -68
- 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/option_merger.rb +3 -1
- data/lib/active_support/ordered_hash.rb +6 -4
- data/lib/active_support/ordered_options.rb +22 -4
- data/lib/active_support/per_thread_registry.rb +13 -6
- 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 +17 -6
- data/lib/active_support/string_inquirer.rb +11 -3
- data/lib/active_support/subscriber.rb +15 -14
- data/lib/active_support/tagged_logging.rb +14 -11
- data/lib/active_support/test_case.rb +18 -46
- 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 +12 -3
- 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 +96 -27
- data/lib/active_support/time.rb +14 -12
- data/lib/active_support/time_with_zone.rb +195 -53
- data/lib/active_support/values/time_zone.rb +200 -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.rb +69 -51
- data/lib/active_support/xml_mini/jdom.rb +116 -113
- data/lib/active_support/xml_mini/libxml.rb +17 -16
- data/lib/active_support/xml_mini/libxmlsax.rb +16 -18
- data/lib/active_support/xml_mini/nokogiri.rb +15 -15
- data/lib/active_support/xml_mini/nokogirisax.rb +15 -16
- data/lib/active_support/xml_mini/rexml.rb +17 -16
- metadata +55 -43
- data/lib/active_support/concurrency/latch.rb +0 -27
- data/lib/active_support/core_ext/big_decimal/yaml_conversions.rb +0 -14
- 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 -11
- 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,4 +1,6 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/concern"
|
2
4
|
|
3
5
|
class Module
|
4
6
|
# = Bite-sized separation of concerns
|
@@ -20,7 +22,7 @@ class Module
|
|
20
22
|
#
|
21
23
|
# == Using comments:
|
22
24
|
#
|
23
|
-
# class Todo
|
25
|
+
# class Todo < ApplicationRecord
|
24
26
|
# # Other todo implementation
|
25
27
|
# # ...
|
26
28
|
#
|
@@ -28,7 +30,6 @@ class Module
|
|
28
30
|
# has_many :events
|
29
31
|
#
|
30
32
|
# before_create :track_creation
|
31
|
-
# after_destroy :track_deletion
|
32
33
|
#
|
33
34
|
# private
|
34
35
|
# def track_creation
|
@@ -40,7 +41,7 @@ class Module
|
|
40
41
|
#
|
41
42
|
# Noisy syntax.
|
42
43
|
#
|
43
|
-
# class Todo
|
44
|
+
# class Todo < ApplicationRecord
|
44
45
|
# # Other todo implementation
|
45
46
|
# # ...
|
46
47
|
#
|
@@ -50,7 +51,6 @@ class Module
|
|
50
51
|
# included do
|
51
52
|
# has_many :events
|
52
53
|
# before_create :track_creation
|
53
|
-
# after_destroy :track_deletion
|
54
54
|
# end
|
55
55
|
#
|
56
56
|
# private
|
@@ -63,12 +63,12 @@ class Module
|
|
63
63
|
#
|
64
64
|
# == Mix-in noise exiled to its own file:
|
65
65
|
#
|
66
|
-
# Once our chunk of behavior starts pushing the scroll-to-understand
|
66
|
+
# Once our chunk of behavior starts pushing the scroll-to-understand-it
|
67
67
|
# boundary, we give in and move it to a separate file. At this size, the
|
68
|
-
# overhead
|
69
|
-
#
|
68
|
+
# increased overhead can be a reasonable tradeoff even if it reduces our
|
69
|
+
# at-a-glance perception of how things work.
|
70
70
|
#
|
71
|
-
# class Todo
|
71
|
+
# class Todo < ApplicationRecord
|
72
72
|
# # Other todo implementation
|
73
73
|
# # ...
|
74
74
|
#
|
@@ -80,7 +80,7 @@ class Module
|
|
80
80
|
# By quieting the mix-in noise, we arrive at a natural, low-ceremony way to
|
81
81
|
# separate bite-sized concerns.
|
82
82
|
#
|
83
|
-
# class Todo
|
83
|
+
# class Todo < ApplicationRecord
|
84
84
|
# # Other todo implementation
|
85
85
|
# # ...
|
86
86
|
#
|
@@ -88,7 +88,6 @@ class Module
|
|
88
88
|
# included do
|
89
89
|
# has_many :events
|
90
90
|
# before_create :track_creation
|
91
|
-
# after_destroy :track_deletion
|
92
91
|
# end
|
93
92
|
#
|
94
93
|
# private
|
@@ -99,7 +98,7 @@ class Module
|
|
99
98
|
# end
|
100
99
|
#
|
101
100
|
# Todo.ancestors
|
102
|
-
# # => Todo, Todo::EventTracking, Object
|
101
|
+
# # => [Todo, Todo::EventTracking, ApplicationRecord, Object]
|
103
102
|
#
|
104
103
|
# This small step has some wonderful ripple effects. We can
|
105
104
|
# * grok the behavior of our class in one glance,
|
@@ -1,14 +1,19 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "set"
|
4
|
+
require "active_support/core_ext/regexp"
|
2
5
|
|
3
6
|
class Module
|
4
7
|
# Error generated by +delegate+ when a method is called on +nil+ and +allow_nil+
|
5
8
|
# option is not used.
|
6
9
|
class DelegationError < NoMethodError; end
|
7
10
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
11
|
+
RUBY_RESERVED_KEYWORDS = %w(alias and BEGIN begin break case class def defined? do
|
12
|
+
else elsif END end ensure false for if in module next nil not or redo rescue retry
|
13
|
+
return self super then true undef unless until when while yield)
|
14
|
+
DELEGATION_RESERVED_KEYWORDS = %w(_ arg args block)
|
15
|
+
DELEGATION_RESERVED_METHOD_NAMES = Set.new(
|
16
|
+
RUBY_RESERVED_KEYWORDS + DELEGATION_RESERVED_KEYWORDS
|
12
17
|
).freeze
|
13
18
|
|
14
19
|
# Provides a +delegate+ class method to easily expose contained objects'
|
@@ -17,7 +22,8 @@ class Module
|
|
17
22
|
# ==== Options
|
18
23
|
# * <tt>:to</tt> - Specifies the target object
|
19
24
|
# * <tt>:prefix</tt> - Prefixes the new method with the target name or a custom prefix
|
20
|
-
# * <tt>:allow_nil</tt> - if set to true, prevents a +
|
25
|
+
# * <tt>:allow_nil</tt> - if set to true, prevents a +Module::DelegationError+
|
26
|
+
# from being raised
|
21
27
|
#
|
22
28
|
# The macro receives one or more method names (specified as symbols or
|
23
29
|
# strings) and the name of the target object via the <tt>:to</tt> option
|
@@ -109,18 +115,16 @@ class Module
|
|
109
115
|
# invoice.customer_address # => 'Vimmersvej 13'
|
110
116
|
#
|
111
117
|
# If the target is +nil+ and does not respond to the delegated method a
|
112
|
-
# +
|
113
|
-
#
|
114
|
-
# <tt>:allow_nil</tt> option: If the target is not +nil+, or it is and
|
115
|
-
# responds to the method, everything works as usual. But if it is +nil+ and
|
116
|
-
# does not respond to the delegated method, +nil+ is returned.
|
118
|
+
# +Module::DelegationError+ is raised. If you wish to instead return +nil+,
|
119
|
+
# use the <tt>:allow_nil</tt> option.
|
117
120
|
#
|
118
121
|
# class User < ActiveRecord::Base
|
119
122
|
# has_one :profile
|
120
123
|
# delegate :age, to: :profile
|
121
124
|
# end
|
122
125
|
#
|
123
|
-
# User.new.age
|
126
|
+
# User.new.age
|
127
|
+
# # => Module::DelegationError: User#age delegated to profile.age, but profile is nil
|
124
128
|
#
|
125
129
|
# But if not having a profile yet is fine and should not be an error
|
126
130
|
# condition:
|
@@ -147,36 +151,32 @@ class Module
|
|
147
151
|
# Foo.new("Bar").name # raises NoMethodError: undefined method `name'
|
148
152
|
#
|
149
153
|
# The target method must be public, otherwise it will raise +NoMethodError+.
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
unless options.is_a?(Hash) && to = options[:to]
|
154
|
-
raise ArgumentError, 'Delegation needs a target. Supply an options hash with a :to key as the last argument (e.g. delegate :hello, to: :greeter).'
|
154
|
+
def delegate(*methods, to: nil, prefix: nil, allow_nil: nil)
|
155
|
+
unless to
|
156
|
+
raise ArgumentError, "Delegation needs a target. Supply an options hash with a :to key as the last argument (e.g. delegate :hello, to: :greeter)."
|
155
157
|
end
|
156
158
|
|
157
|
-
prefix
|
158
|
-
|
159
|
-
if prefix == true && to =~ /^[^a-z_]/
|
160
|
-
raise ArgumentError, 'Can only automatically set the delegation prefix when delegating to a method.'
|
159
|
+
if prefix == true && /^[^a-z_]/.match?(to)
|
160
|
+
raise ArgumentError, "Can only automatically set the delegation prefix when delegating to a method."
|
161
161
|
end
|
162
162
|
|
163
163
|
method_prefix = \
|
164
164
|
if prefix
|
165
165
|
"#{prefix == true ? to : prefix}_"
|
166
166
|
else
|
167
|
-
|
167
|
+
""
|
168
168
|
end
|
169
169
|
|
170
|
-
|
171
|
-
line =
|
170
|
+
location = caller_locations(1, 1).first
|
171
|
+
file, line = location.path, location.lineno
|
172
172
|
|
173
173
|
to = to.to_s
|
174
|
-
to = "self.#{to}" if
|
174
|
+
to = "self.#{to}" if DELEGATION_RESERVED_METHOD_NAMES.include?(to)
|
175
175
|
|
176
|
-
methods.
|
176
|
+
methods.map do |method|
|
177
177
|
# Attribute writer methods only accept one argument. Makes sure []=
|
178
178
|
# methods still accept two arguments.
|
179
|
-
definition =
|
179
|
+
definition = /[^\]]=$/.match?(method) ? "arg" : "*args, &block"
|
180
180
|
|
181
181
|
# The following generated method calls the target exactly once, storing
|
182
182
|
# the returned value in a dummy variable.
|
@@ -185,21 +185,103 @@ class Module
|
|
185
185
|
# On the other hand it could be that the target has side-effects,
|
186
186
|
# whereas conceptually, from the user point of view, the delegator should
|
187
187
|
# be doing one call.
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
" _.#{method}(#{definition})",
|
196
|
-
" else",
|
197
|
-
" #{exception unless allow_nil}",
|
198
|
-
" end",
|
188
|
+
if allow_nil
|
189
|
+
method_def = [
|
190
|
+
"def #{method_prefix}#{method}(#{definition})",
|
191
|
+
"_ = #{to}",
|
192
|
+
"if !_.nil? || nil.respond_to?(:#{method})",
|
193
|
+
" _.#{method}(#{definition})",
|
194
|
+
"end",
|
199
195
|
"end"
|
200
|
-
|
196
|
+
].join ";"
|
197
|
+
else
|
198
|
+
exception = %(raise DelegationError, "#{self}##{method_prefix}#{method} delegated to #{to}.#{method}, but #{to} is nil: \#{self.inspect}")
|
199
|
+
|
200
|
+
method_def = [
|
201
|
+
"def #{method_prefix}#{method}(#{definition})",
|
202
|
+
" _ = #{to}",
|
203
|
+
" _.#{method}(#{definition})",
|
204
|
+
"rescue NoMethodError => e",
|
205
|
+
" if _.nil? && e.name == :#{method}",
|
206
|
+
" #{exception}",
|
207
|
+
" else",
|
208
|
+
" raise",
|
209
|
+
" end",
|
210
|
+
"end"
|
211
|
+
].join ";"
|
212
|
+
end
|
201
213
|
|
202
214
|
module_eval(method_def, file, line)
|
203
215
|
end
|
204
216
|
end
|
217
|
+
|
218
|
+
# When building decorators, a common pattern may emerge:
|
219
|
+
#
|
220
|
+
# class Partition
|
221
|
+
# def initialize(event)
|
222
|
+
# @event = event
|
223
|
+
# end
|
224
|
+
#
|
225
|
+
# def person
|
226
|
+
# @event.detail.person || @event.creator
|
227
|
+
# end
|
228
|
+
#
|
229
|
+
# private
|
230
|
+
# def respond_to_missing?(name, include_private = false)
|
231
|
+
# @event.respond_to?(name, include_private)
|
232
|
+
# end
|
233
|
+
#
|
234
|
+
# def method_missing(method, *args, &block)
|
235
|
+
# @event.send(method, *args, &block)
|
236
|
+
# end
|
237
|
+
# end
|
238
|
+
#
|
239
|
+
# With <tt>Module#delegate_missing_to</tt>, the above is condensed to:
|
240
|
+
#
|
241
|
+
# class Partition
|
242
|
+
# delegate_missing_to :@event
|
243
|
+
#
|
244
|
+
# def initialize(event)
|
245
|
+
# @event = event
|
246
|
+
# end
|
247
|
+
#
|
248
|
+
# def person
|
249
|
+
# @event.detail.person || @event.creator
|
250
|
+
# end
|
251
|
+
# end
|
252
|
+
#
|
253
|
+
# The target can be anything callable within the object, e.g. instance
|
254
|
+
# variables, methods, constants, etc.
|
255
|
+
#
|
256
|
+
# The delegated method must be public on the target, otherwise it will
|
257
|
+
# raise +NoMethodError+.
|
258
|
+
def delegate_missing_to(target)
|
259
|
+
target = target.to_s
|
260
|
+
target = "self.#{target}" if DELEGATION_RESERVED_METHOD_NAMES.include?(target)
|
261
|
+
|
262
|
+
module_eval <<-RUBY, __FILE__, __LINE__ + 1
|
263
|
+
def respond_to_missing?(name, include_private = false)
|
264
|
+
# It may look like an oversight, but we deliberately do not pass
|
265
|
+
# +include_private+, because they do not get delegated.
|
266
|
+
|
267
|
+
#{target}.respond_to?(name) || super
|
268
|
+
end
|
269
|
+
|
270
|
+
def method_missing(method, *args, &block)
|
271
|
+
if #{target}.respond_to?(method)
|
272
|
+
#{target}.public_send(method, *args, &block)
|
273
|
+
else
|
274
|
+
begin
|
275
|
+
super
|
276
|
+
rescue NoMethodError
|
277
|
+
if #{target}.nil?
|
278
|
+
raise DelegationError, "\#{method} delegated to #{target}, but #{target} is nil"
|
279
|
+
else
|
280
|
+
raise
|
281
|
+
end
|
282
|
+
end
|
283
|
+
end
|
284
|
+
end
|
285
|
+
RUBY
|
286
|
+
end
|
205
287
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class Module
|
2
4
|
# deprecate :foo
|
3
5
|
# deprecate bar: 'message'
|
@@ -13,8 +15,8 @@ class Module
|
|
13
15
|
#
|
14
16
|
# class MyLib::Deprecator
|
15
17
|
# def deprecation_warning(deprecated_method_name, message, caller_backtrace = nil)
|
16
|
-
#
|
17
|
-
#
|
18
|
+
# message = "#{deprecated_method_name} is deprecated and will be removed from MyLibrary | #{message}"
|
19
|
+
# Kernel.warn message
|
18
20
|
# end
|
19
21
|
# end
|
20
22
|
def deprecate(*method_names)
|
@@ -1,14 +1,18 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/inflector"
|
2
4
|
|
3
5
|
class Module
|
4
6
|
# Returns the name of the module containing this one.
|
5
7
|
#
|
6
8
|
# M::N.parent_name # => "M"
|
7
9
|
def parent_name
|
8
|
-
if defined?
|
10
|
+
if defined?(@parent_name)
|
9
11
|
@parent_name
|
10
12
|
else
|
11
|
-
|
13
|
+
parent_name = name =~ /::[^:]+\Z/ ? $`.freeze : nil
|
14
|
+
@parent_name = parent_name unless frozen?
|
15
|
+
parent_name
|
12
16
|
end
|
13
17
|
end
|
14
18
|
|
@@ -46,17 +50,13 @@ class Module
|
|
46
50
|
def parents
|
47
51
|
parents = []
|
48
52
|
if parent_name
|
49
|
-
parts = parent_name.split(
|
53
|
+
parts = parent_name.split("::")
|
50
54
|
until parts.empty?
|
51
|
-
parents << ActiveSupport::Inflector.constantize(parts *
|
55
|
+
parents << ActiveSupport::Inflector.constantize(parts * "::")
|
52
56
|
parts.pop
|
53
57
|
end
|
54
58
|
end
|
55
59
|
parents << Object unless parents.include? Object
|
56
60
|
parents
|
57
61
|
end
|
58
|
-
|
59
|
-
def local_constants #:nodoc:
|
60
|
-
constants(false)
|
61
|
-
end
|
62
62
|
end
|
@@ -1,8 +1,11 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/core_ext/module/anonymous"
|
4
|
+
require "active_support/core_ext/string/inflections"
|
3
5
|
|
4
6
|
class Module
|
5
7
|
def reachable? #:nodoc:
|
6
8
|
!anonymous? && name.safe_constantize.equal?(self)
|
7
9
|
end
|
10
|
+
deprecate :reachable?
|
8
11
|
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Module
|
4
|
+
if RUBY_VERSION >= "2.3"
|
5
|
+
# Marks the named method as intended to be redefined, if it exists.
|
6
|
+
# Suppresses the Ruby method redefinition warning. Prefer
|
7
|
+
# #redefine_method where possible.
|
8
|
+
def silence_redefinition_of_method(method)
|
9
|
+
if method_defined?(method) || private_method_defined?(method)
|
10
|
+
# This suppresses the "method redefined" warning; the self-alias
|
11
|
+
# looks odd, but means we don't need to generate a unique name
|
12
|
+
alias_method method, method
|
13
|
+
end
|
14
|
+
end
|
15
|
+
else
|
16
|
+
def silence_redefinition_of_method(method)
|
17
|
+
if method_defined?(method) || private_method_defined?(method)
|
18
|
+
alias_method :__rails_redefine, method
|
19
|
+
remove_method :__rails_redefine
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# Replaces the existing method definition, if there is one, with the passed
|
25
|
+
# block as its body.
|
26
|
+
def redefine_method(method, &block)
|
27
|
+
visibility = method_visibility(method)
|
28
|
+
silence_redefinition_of_method(method)
|
29
|
+
define_method(method, &block)
|
30
|
+
send(visibility, method)
|
31
|
+
end
|
32
|
+
|
33
|
+
# Replaces the existing singleton method definition, if there is one, with
|
34
|
+
# the passed block as its body.
|
35
|
+
def redefine_singleton_method(method, &block)
|
36
|
+
singleton_class.redefine_method(method, &block)
|
37
|
+
end
|
38
|
+
|
39
|
+
def method_visibility(method) # :nodoc:
|
40
|
+
case
|
41
|
+
when private_method_defined?(method)
|
42
|
+
:private
|
43
|
+
when protected_method_defined?(method)
|
44
|
+
:protected
|
45
|
+
else
|
46
|
+
:public
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -1,12 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/core_ext/module/redefine_method"
|
4
|
+
|
1
5
|
class Module
|
6
|
+
# Removes the named method, if it exists.
|
2
7
|
def remove_possible_method(method)
|
3
8
|
if method_defined?(method) || private_method_defined?(method)
|
4
9
|
undef_method(method)
|
5
10
|
end
|
6
11
|
end
|
7
12
|
|
8
|
-
|
9
|
-
|
10
|
-
|
13
|
+
# Removes the named singleton method, if it exists.
|
14
|
+
def remove_possible_singleton_method(method)
|
15
|
+
singleton_class.remove_possible_method(method)
|
11
16
|
end
|
12
17
|
end
|