activesupport 5.2.4.4 → 6.1.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 +353 -435
- data/MIT-LICENSE +1 -1
- data/README.rdoc +4 -3
- data/lib/active_support.rb +14 -1
- data/lib/active_support/actionable_error.rb +48 -0
- data/lib/active_support/array_inquirer.rb +4 -2
- data/lib/active_support/backtrace_cleaner.rb +29 -3
- data/lib/active_support/benchmarkable.rb +1 -1
- data/lib/active_support/cache.rb +142 -78
- data/lib/active_support/cache/file_store.rb +33 -33
- data/lib/active_support/cache/mem_cache_store.rb +32 -20
- data/lib/active_support/cache/memory_store.rb +59 -33
- data/lib/active_support/cache/null_store.rb +8 -3
- data/lib/active_support/cache/redis_cache_store.rb +70 -43
- data/lib/active_support/cache/strategy/local_cache.rb +41 -26
- data/lib/active_support/callbacks.rb +81 -64
- data/lib/active_support/concern.rb +70 -3
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +18 -0
- data/lib/active_support/concurrency/share_lock.rb +0 -1
- data/lib/active_support/configurable.rb +10 -14
- data/lib/active_support/configuration_file.rb +46 -0
- data/lib/active_support/core_ext.rb +1 -1
- data/lib/active_support/core_ext/array.rb +1 -1
- data/lib/active_support/core_ext/array/access.rb +18 -6
- data/lib/active_support/core_ext/array/conversions.rb +5 -5
- data/lib/active_support/core_ext/array/extract.rb +21 -0
- data/lib/active_support/core_ext/benchmark.rb +2 -2
- data/lib/active_support/core_ext/class/attribute.rb +32 -47
- data/lib/active_support/core_ext/class/subclasses.rb +17 -38
- data/lib/active_support/core_ext/date/calculations.rb +6 -5
- data/lib/active_support/core_ext/date/conversions.rb +2 -1
- data/lib/active_support/core_ext/date_and_time/calculations.rb +37 -47
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +15 -0
- data/lib/active_support/core_ext/date_and_time/zones.rb +0 -1
- data/lib/active_support/core_ext/date_time/calculations.rb +1 -1
- data/lib/active_support/core_ext/date_time/conversions.rb +0 -1
- data/lib/active_support/core_ext/enumerable.rb +171 -75
- data/lib/active_support/core_ext/hash.rb +1 -2
- data/lib/active_support/core_ext/hash/conversions.rb +3 -3
- data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
- data/lib/active_support/core_ext/hash/except.rb +2 -2
- data/lib/active_support/core_ext/hash/keys.rb +1 -30
- data/lib/active_support/core_ext/hash/slice.rb +6 -27
- data/lib/active_support/core_ext/integer/multiple.rb +1 -1
- data/lib/active_support/core_ext/kernel.rb +0 -1
- data/lib/active_support/core_ext/load_error.rb +1 -1
- data/lib/active_support/core_ext/marshal.rb +2 -0
- data/lib/active_support/core_ext/module.rb +0 -1
- data/lib/active_support/core_ext/module/attr_internal.rb +2 -2
- data/lib/active_support/core_ext/module/attribute_accessors.rb +30 -39
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +17 -19
- data/lib/active_support/core_ext/module/concerning.rb +8 -2
- data/lib/active_support/core_ext/module/delegation.rb +76 -33
- data/lib/active_support/core_ext/module/introspection.rb +16 -15
- data/lib/active_support/core_ext/module/redefine_method.rb +8 -17
- data/lib/active_support/core_ext/name_error.rb +29 -2
- data/lib/active_support/core_ext/numeric.rb +0 -1
- data/lib/active_support/core_ext/numeric/conversions.rb +129 -129
- data/lib/active_support/core_ext/object/blank.rb +1 -2
- data/lib/active_support/core_ext/object/deep_dup.rb +1 -1
- data/lib/active_support/core_ext/object/duplicable.rb +7 -114
- data/lib/active_support/core_ext/object/json.rb +14 -2
- data/lib/active_support/core_ext/object/try.rb +17 -7
- data/lib/active_support/core_ext/object/with_options.rb +1 -1
- data/lib/active_support/core_ext/range/compare_range.rb +34 -13
- data/lib/active_support/core_ext/range/conversions.rb +31 -29
- data/lib/active_support/core_ext/range/each.rb +0 -1
- data/lib/active_support/core_ext/range/include_time_with_zone.rb +8 -3
- data/lib/active_support/core_ext/regexp.rb +8 -5
- data/lib/active_support/core_ext/securerandom.rb +23 -3
- data/lib/active_support/core_ext/string/access.rb +5 -16
- data/lib/active_support/core_ext/string/conversions.rb +1 -0
- data/lib/active_support/core_ext/string/filters.rb +42 -1
- data/lib/active_support/core_ext/string/inflections.rb +45 -6
- data/lib/active_support/core_ext/string/inquiry.rb +1 -0
- data/lib/active_support/core_ext/string/multibyte.rb +6 -5
- data/lib/active_support/core_ext/string/output_safety.rb +70 -13
- data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -2
- data/lib/active_support/core_ext/string/strip.rb +3 -1
- data/lib/active_support/core_ext/symbol.rb +3 -0
- data/lib/active_support/core_ext/symbol/starts_ends_with.rb +14 -0
- data/lib/active_support/core_ext/time/calculations.rb +50 -3
- data/lib/active_support/core_ext/time/conversions.rb +2 -0
- data/lib/active_support/core_ext/uri.rb +6 -1
- data/lib/active_support/current_attributes.rb +15 -2
- data/lib/active_support/current_attributes/test_helper.rb +13 -0
- data/lib/active_support/dependencies.rb +109 -34
- data/lib/active_support/dependencies/zeitwerk_integration.rb +117 -0
- data/lib/active_support/deprecation.rb +6 -1
- data/lib/active_support/deprecation/behaviors.rb +16 -3
- data/lib/active_support/deprecation/disallowed.rb +56 -0
- data/lib/active_support/deprecation/instance_delegator.rb +0 -1
- data/lib/active_support/deprecation/method_wrappers.rb +18 -23
- data/lib/active_support/deprecation/proxy_wrappers.rb +29 -6
- data/lib/active_support/deprecation/reporting.rb +50 -7
- data/lib/active_support/descendants_tracker.rb +59 -9
- data/lib/active_support/duration.rb +90 -38
- data/lib/active_support/duration/iso8601_parser.rb +2 -4
- data/lib/active_support/duration/iso8601_serializer.rb +18 -14
- data/lib/active_support/encrypted_configuration.rb +0 -4
- data/lib/active_support/encrypted_file.rb +22 -4
- data/lib/active_support/environment_inquirer.rb +20 -0
- data/lib/active_support/evented_file_update_checker.rb +82 -117
- data/lib/active_support/execution_wrapper.rb +1 -0
- data/lib/active_support/file_update_checker.rb +0 -1
- data/lib/active_support/fork_tracker.rb +62 -0
- data/lib/active_support/gem_version.rb +4 -4
- data/lib/active_support/hash_with_indifferent_access.rb +64 -41
- data/lib/active_support/i18n.rb +1 -0
- data/lib/active_support/i18n_railtie.rb +15 -8
- data/lib/active_support/inflector/inflections.rb +2 -7
- data/lib/active_support/inflector/methods.rb +49 -58
- data/lib/active_support/inflector/transliterate.rb +47 -18
- data/lib/active_support/json/decoding.rb +25 -26
- data/lib/active_support/json/encoding.rb +11 -3
- data/lib/active_support/key_generator.rb +1 -33
- data/lib/active_support/lazy_load_hooks.rb +5 -2
- data/lib/active_support/locale/en.rb +33 -0
- data/lib/active_support/locale/en.yml +7 -3
- data/lib/active_support/log_subscriber.rb +39 -9
- data/lib/active_support/logger.rb +2 -17
- data/lib/active_support/logger_silence.rb +11 -19
- data/lib/active_support/logger_thread_safe_level.rb +50 -6
- data/lib/active_support/message_encryptor.rb +8 -13
- data/lib/active_support/message_verifier.rb +10 -10
- data/lib/active_support/messages/metadata.rb +11 -2
- data/lib/active_support/messages/rotation_configuration.rb +2 -1
- data/lib/active_support/messages/rotator.rb +10 -9
- data/lib/active_support/multibyte/chars.rb +10 -68
- data/lib/active_support/multibyte/unicode.rb +15 -327
- data/lib/active_support/notifications.rb +72 -8
- data/lib/active_support/notifications/fanout.rb +116 -16
- data/lib/active_support/notifications/instrumenter.rb +71 -9
- data/lib/active_support/number_helper.rb +38 -12
- data/lib/active_support/number_helper/number_converter.rb +5 -6
- data/lib/active_support/number_helper/number_to_currency_converter.rb +4 -9
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +3 -2
- data/lib/active_support/number_helper/number_to_human_converter.rb +4 -3
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +4 -3
- data/lib/active_support/number_helper/number_to_percentage_converter.rb +3 -1
- data/lib/active_support/number_helper/number_to_phone_converter.rb +2 -1
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +8 -7
- data/lib/active_support/number_helper/rounding_helper.rb +12 -28
- data/lib/active_support/option_merger.rb +22 -3
- data/lib/active_support/ordered_hash.rb +1 -1
- data/lib/active_support/ordered_options.rb +13 -3
- data/lib/active_support/parameter_filter.rb +133 -0
- data/lib/active_support/per_thread_registry.rb +1 -1
- data/lib/active_support/rails.rb +1 -10
- data/lib/active_support/railtie.rb +23 -1
- data/lib/active_support/reloader.rb +4 -5
- data/lib/active_support/rescuable.rb +4 -4
- data/lib/active_support/secure_compare_rotator.rb +51 -0
- data/lib/active_support/security_utils.rb +19 -12
- data/lib/active_support/string_inquirer.rb +4 -3
- data/lib/active_support/subscriber.rb +72 -28
- data/lib/active_support/tagged_logging.rb +42 -8
- data/lib/active_support/test_case.rb +91 -0
- data/lib/active_support/testing/assertions.rb +30 -9
- data/lib/active_support/testing/deprecation.rb +0 -1
- data/lib/active_support/testing/file_fixtures.rb +2 -0
- data/lib/active_support/testing/isolation.rb +2 -2
- data/lib/active_support/testing/method_call_assertions.rb +28 -1
- data/lib/active_support/testing/parallelization.rb +51 -0
- data/lib/active_support/testing/parallelization/server.rb +78 -0
- data/lib/active_support/testing/parallelization/worker.rb +100 -0
- data/lib/active_support/testing/stream.rb +1 -2
- data/lib/active_support/testing/time_helpers.rb +47 -12
- data/lib/active_support/time_with_zone.rb +81 -47
- data/lib/active_support/values/time_zone.rb +32 -17
- data/lib/active_support/xml_mini.rb +2 -10
- data/lib/active_support/xml_mini/jdom.rb +2 -3
- data/lib/active_support/xml_mini/libxml.rb +2 -2
- data/lib/active_support/xml_mini/libxmlsax.rb +4 -4
- data/lib/active_support/xml_mini/nokogiri.rb +2 -2
- data/lib/active_support/xml_mini/nokogirisax.rb +3 -3
- data/lib/active_support/xml_mini/rexml.rb +10 -3
- metadata +58 -32
- data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -9
- data/lib/active_support/core_ext/hash/compact.rb +0 -29
- data/lib/active_support/core_ext/hash/transform_values.rb +0 -32
- data/lib/active_support/core_ext/kernel/agnostics.rb +0 -13
- data/lib/active_support/core_ext/module/reachable.rb +0 -11
- data/lib/active_support/core_ext/numeric/inquiry.rb +0 -28
- data/lib/active_support/core_ext/range/include_range.rb +0 -3
- data/lib/active_support/values/unicode_tables.dat +0 -0
@@ -19,7 +19,7 @@ module ActiveSupport
|
|
19
19
|
# By using <tt>ActiveSupport::Concern</tt> the above module could instead be
|
20
20
|
# written as:
|
21
21
|
#
|
22
|
-
# require
|
22
|
+
# require "active_support/concern"
|
23
23
|
#
|
24
24
|
# module M
|
25
25
|
# extend ActiveSupport::Concern
|
@@ -76,7 +76,7 @@ module ActiveSupport
|
|
76
76
|
# is the +Bar+ module, not the +Host+ class. With <tt>ActiveSupport::Concern</tt>,
|
77
77
|
# module dependencies are properly resolved:
|
78
78
|
#
|
79
|
-
# require
|
79
|
+
# require "active_support/concern"
|
80
80
|
#
|
81
81
|
# module Foo
|
82
82
|
# extend ActiveSupport::Concern
|
@@ -99,6 +99,14 @@ module ActiveSupport
|
|
99
99
|
# class Host
|
100
100
|
# include Bar # It works, now Bar takes care of its dependencies
|
101
101
|
# end
|
102
|
+
#
|
103
|
+
# === Prepending concerns
|
104
|
+
#
|
105
|
+
# Just like <tt>include</tt>, concerns also support <tt>prepend</tt> with a corresponding
|
106
|
+
# <tt>prepended do</tt> callback. <tt>module ClassMethods</tt> or <tt>class_methods do</tt> are
|
107
|
+
# prepended as well.
|
108
|
+
#
|
109
|
+
# <tt>prepend</tt> is also used for any dependencies.
|
102
110
|
module Concern
|
103
111
|
class MultipleIncludedBlocks < StandardError #:nodoc:
|
104
112
|
def initialize
|
@@ -106,11 +114,17 @@ module ActiveSupport
|
|
106
114
|
end
|
107
115
|
end
|
108
116
|
|
117
|
+
class MultiplePrependBlocks < StandardError #:nodoc:
|
118
|
+
def initialize
|
119
|
+
super "Cannot define multiple 'prepended' blocks for a Concern"
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
109
123
|
def self.extended(base) #:nodoc:
|
110
124
|
base.instance_variable_set(:@_dependencies, [])
|
111
125
|
end
|
112
126
|
|
113
|
-
def append_features(base)
|
127
|
+
def append_features(base) #:nodoc:
|
114
128
|
if base.instance_variable_defined?(:@_dependencies)
|
115
129
|
base.instance_variable_get(:@_dependencies) << self
|
116
130
|
false
|
@@ -123,6 +137,22 @@ module ActiveSupport
|
|
123
137
|
end
|
124
138
|
end
|
125
139
|
|
140
|
+
def prepend_features(base) #:nodoc:
|
141
|
+
if base.instance_variable_defined?(:@_dependencies)
|
142
|
+
base.instance_variable_get(:@_dependencies).unshift self
|
143
|
+
false
|
144
|
+
else
|
145
|
+
return false if base < self
|
146
|
+
@_dependencies.each { |dep| base.prepend(dep) }
|
147
|
+
super
|
148
|
+
base.singleton_class.prepend const_get(:ClassMethods) if const_defined?(:ClassMethods)
|
149
|
+
base.class_eval(&@_prepended_block) if instance_variable_defined?(:@_prepended_block)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
# Evaluate given block in context of base class,
|
154
|
+
# so that you can write class macros here.
|
155
|
+
# When you define more than one +included+ block, it raises an exception.
|
126
156
|
def included(base = nil, &block)
|
127
157
|
if base.nil?
|
128
158
|
if instance_variable_defined?(:@_included_block)
|
@@ -137,6 +167,43 @@ module ActiveSupport
|
|
137
167
|
end
|
138
168
|
end
|
139
169
|
|
170
|
+
# Evaluate given block in context of base class,
|
171
|
+
# so that you can write class macros here.
|
172
|
+
# When you define more than one +prepended+ block, it raises an exception.
|
173
|
+
def prepended(base = nil, &block)
|
174
|
+
if base.nil?
|
175
|
+
if instance_variable_defined?(:@_prepended_block)
|
176
|
+
if @_prepended_block.source_location != block.source_location
|
177
|
+
raise MultiplePrependBlocks
|
178
|
+
end
|
179
|
+
else
|
180
|
+
@_prepended_block = block
|
181
|
+
end
|
182
|
+
else
|
183
|
+
super
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
# Define class methods from given block.
|
188
|
+
# You can define private class methods as well.
|
189
|
+
#
|
190
|
+
# module Example
|
191
|
+
# extend ActiveSupport::Concern
|
192
|
+
#
|
193
|
+
# class_methods do
|
194
|
+
# def foo; puts 'foo'; end
|
195
|
+
#
|
196
|
+
# private
|
197
|
+
# def bar; puts 'bar'; end
|
198
|
+
# end
|
199
|
+
# end
|
200
|
+
#
|
201
|
+
# class Buzz
|
202
|
+
# include Example
|
203
|
+
# end
|
204
|
+
#
|
205
|
+
# Buzz.foo # => "foo"
|
206
|
+
# Buzz.bar # => private method 'bar' called for Buzz:Class(NoMethodError)
|
140
207
|
def class_methods(&class_methods_module_definition)
|
141
208
|
mod = const_defined?(:ClassMethods, false) ?
|
142
209
|
const_get(:ClassMethods) :
|
@@ -7,11 +7,29 @@ module ActiveSupport
|
|
7
7
|
# A monitor that will permit dependency loading while blocked waiting for
|
8
8
|
# the lock.
|
9
9
|
class LoadInterlockAwareMonitor < Monitor
|
10
|
+
EXCEPTION_NEVER = { Exception => :never }.freeze
|
11
|
+
EXCEPTION_IMMEDIATE = { Exception => :immediate }.freeze
|
12
|
+
private_constant :EXCEPTION_NEVER, :EXCEPTION_IMMEDIATE
|
13
|
+
|
10
14
|
# Enters an exclusive section, but allows dependency loading while blocked
|
11
15
|
def mon_enter
|
12
16
|
mon_try_enter ||
|
13
17
|
ActiveSupport::Dependencies.interlock.permit_concurrent_loads { super }
|
14
18
|
end
|
19
|
+
|
20
|
+
def synchronize
|
21
|
+
Thread.handle_interrupt(EXCEPTION_NEVER) do
|
22
|
+
mon_enter
|
23
|
+
|
24
|
+
begin
|
25
|
+
Thread.handle_interrupt(EXCEPTION_IMMEDIATE) do
|
26
|
+
yield
|
27
|
+
end
|
28
|
+
ensure
|
29
|
+
mon_exit
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
15
33
|
end
|
16
34
|
end
|
17
35
|
end
|
@@ -2,12 +2,10 @@
|
|
2
2
|
|
3
3
|
require "active_support/concern"
|
4
4
|
require "active_support/ordered_options"
|
5
|
-
require "active_support/core_ext/array/extract_options"
|
6
|
-
require "active_support/core_ext/regexp"
|
7
5
|
|
8
6
|
module ActiveSupport
|
9
7
|
# Configurable provides a <tt>config</tt> method to store and retrieve
|
10
|
-
# configuration options as an <tt>
|
8
|
+
# configuration options as an <tt>OrderedOptions</tt>.
|
11
9
|
module Configurable
|
12
10
|
extend ActiveSupport::Concern
|
13
11
|
|
@@ -69,8 +67,8 @@ module ActiveSupport
|
|
69
67
|
# end
|
70
68
|
# # => NameError: invalid config attribute name
|
71
69
|
#
|
72
|
-
# To
|
73
|
-
# To
|
70
|
+
# To omit the instance writer method, pass <tt>instance_writer: false</tt>.
|
71
|
+
# To omit the instance reader method, pass <tt>instance_reader: false</tt>.
|
74
72
|
#
|
75
73
|
# class User
|
76
74
|
# include ActiveSupport::Configurable
|
@@ -83,7 +81,7 @@ module ActiveSupport
|
|
83
81
|
# User.new.allowed_access = true # => NoMethodError
|
84
82
|
# User.new.allowed_access # => NoMethodError
|
85
83
|
#
|
86
|
-
# Or pass <tt>instance_accessor: false</tt>, to
|
84
|
+
# Or pass <tt>instance_accessor: false</tt>, to omit both instance methods.
|
87
85
|
#
|
88
86
|
# class User
|
89
87
|
# include ActiveSupport::Configurable
|
@@ -106,9 +104,7 @@ module ActiveSupport
|
|
106
104
|
# end
|
107
105
|
#
|
108
106
|
# User.hair_colors # => [:brown, :black, :blonde, :red]
|
109
|
-
def config_accessor(*names)
|
110
|
-
options = names.extract_options!
|
111
|
-
|
107
|
+
def config_accessor(*names, instance_reader: true, instance_writer: true, instance_accessor: true) # :doc:
|
112
108
|
names.each do |name|
|
113
109
|
raise NameError.new("invalid config attribute name") unless /\A[_A-Za-z]\w*\z/.match?(name)
|
114
110
|
|
@@ -118,9 +114,9 @@ module ActiveSupport
|
|
118
114
|
singleton_class.class_eval reader, __FILE__, reader_line
|
119
115
|
singleton_class.class_eval writer, __FILE__, writer_line
|
120
116
|
|
121
|
-
|
122
|
-
class_eval reader, __FILE__, reader_line
|
123
|
-
class_eval writer, __FILE__, writer_line
|
117
|
+
if instance_accessor
|
118
|
+
class_eval reader, __FILE__, reader_line if instance_reader
|
119
|
+
class_eval writer, __FILE__, writer_line if instance_writer
|
124
120
|
end
|
125
121
|
send("#{name}=", yield) if block_given?
|
126
122
|
end
|
@@ -128,9 +124,9 @@ module ActiveSupport
|
|
128
124
|
private :config_accessor
|
129
125
|
end
|
130
126
|
|
131
|
-
# Reads and writes attributes from a configuration <tt>
|
127
|
+
# Reads and writes attributes from a configuration <tt>OrderedOptions</tt>.
|
132
128
|
#
|
133
|
-
# require
|
129
|
+
# require "active_support/configurable"
|
134
130
|
#
|
135
131
|
# class User
|
136
132
|
# include ActiveSupport::Configurable
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveSupport
|
4
|
+
# Reads a YAML configuration file, evaluating any ERB, then
|
5
|
+
# parsing the resulting YAML.
|
6
|
+
#
|
7
|
+
# Warns in case of YAML confusing characters, like invisible
|
8
|
+
# non-breaking spaces.
|
9
|
+
class ConfigurationFile # :nodoc:
|
10
|
+
class FormatError < StandardError; end
|
11
|
+
|
12
|
+
def initialize(content_path)
|
13
|
+
@content_path = content_path.to_s
|
14
|
+
@content = read content_path
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.parse(content_path, **options)
|
18
|
+
new(content_path).parse(**options)
|
19
|
+
end
|
20
|
+
|
21
|
+
def parse(context: nil, **options)
|
22
|
+
YAML.load(render(context), **options) || {}
|
23
|
+
rescue Psych::SyntaxError => error
|
24
|
+
raise "YAML syntax error occurred while parsing #{@content_path}. " \
|
25
|
+
"Please note that YAML must be consistently indented using spaces. Tabs are not allowed. " \
|
26
|
+
"Error: #{error.message}"
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
def read(content_path)
|
31
|
+
require "yaml"
|
32
|
+
require "erb"
|
33
|
+
|
34
|
+
File.read(content_path).tap do |content|
|
35
|
+
if content.include?("\u00A0")
|
36
|
+
warn "File contains invisible non-breaking spaces, you may want to remove those"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def render(context)
|
42
|
+
erb = ERB.new(@content).tap { |e| e.filename = @content_path }
|
43
|
+
context ? erb.result(context) : erb.result
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -3,7 +3,7 @@
|
|
3
3
|
require "active_support/core_ext/array/wrap"
|
4
4
|
require "active_support/core_ext/array/access"
|
5
5
|
require "active_support/core_ext/array/conversions"
|
6
|
+
require "active_support/core_ext/array/extract"
|
6
7
|
require "active_support/core_ext/array/extract_options"
|
7
8
|
require "active_support/core_ext/array/grouping"
|
8
|
-
require "active_support/core_ext/array/prepend_and_append"
|
9
9
|
require "active_support/core_ext/array/inquiry"
|
@@ -29,16 +29,28 @@ class Array
|
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
|
-
# Returns a
|
32
|
+
# Returns a new array that includes the passed elements.
|
33
33
|
#
|
34
|
-
#
|
35
|
-
#
|
36
|
-
|
34
|
+
# [ 1, 2, 3 ].including(4, 5) # => [ 1, 2, 3, 4, 5 ]
|
35
|
+
# [ [ 0, 1 ] ].including([ [ 1, 0 ] ]) # => [ [ 0, 1 ], [ 1, 0 ] ]
|
36
|
+
def including(*elements)
|
37
|
+
self + elements.flatten(1)
|
38
|
+
end
|
39
|
+
|
40
|
+
# Returns a copy of the Array excluding the specified elements.
|
41
|
+
#
|
42
|
+
# ["David", "Rafael", "Aaron", "Todd"].excluding("Aaron", "Todd") # => ["David", "Rafael"]
|
43
|
+
# [ [ 0, 1 ], [ 1, 0 ] ].excluding([ [ 1, 0 ] ]) # => [ [ 0, 1 ] ]
|
37
44
|
#
|
38
|
-
# Note: This is an optimization of <tt>Enumerable#
|
45
|
+
# Note: This is an optimization of <tt>Enumerable#excluding</tt> that uses <tt>Array#-</tt>
|
39
46
|
# instead of <tt>Array#reject</tt> for performance reasons.
|
47
|
+
def excluding(*elements)
|
48
|
+
self - elements.flatten(1)
|
49
|
+
end
|
50
|
+
|
51
|
+
# Alias for #excluding.
|
40
52
|
def without(*elements)
|
41
|
-
|
53
|
+
excluding(*elements)
|
42
54
|
end
|
43
55
|
|
44
56
|
# Equal to <tt>self[1]</tt>.
|
@@ -74,13 +74,13 @@ class Array
|
|
74
74
|
|
75
75
|
case length
|
76
76
|
when 0
|
77
|
-
""
|
77
|
+
+""
|
78
78
|
when 1
|
79
|
-
"#{self[0]}"
|
79
|
+
+"#{self[0]}"
|
80
80
|
when 2
|
81
|
-
"#{self[0]}#{options[:two_words_connector]}#{self[1]}"
|
81
|
+
+"#{self[0]}#{options[:two_words_connector]}#{self[1]}"
|
82
82
|
else
|
83
|
-
"#{self[0...-1].join(options[:words_connector])}#{options[:last_word_connector]}#{self[-1]}"
|
83
|
+
+"#{self[0...-1].join(options[:words_connector])}#{options[:last_word_connector]}#{self[-1]}"
|
84
84
|
end
|
85
85
|
end
|
86
86
|
|
@@ -181,7 +181,7 @@ class Array
|
|
181
181
|
# </messages>
|
182
182
|
#
|
183
183
|
def to_xml(options = {})
|
184
|
-
require "active_support/builder" unless defined?(Builder)
|
184
|
+
require "active_support/builder" unless defined?(Builder::XmlMarkup)
|
185
185
|
|
186
186
|
options = options.dup
|
187
187
|
options[:indent] ||= 2
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Array
|
4
|
+
# Removes and returns the elements for which the block returns a true value.
|
5
|
+
# If no block is given, an Enumerator is returned instead.
|
6
|
+
#
|
7
|
+
# numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
8
|
+
# odd_numbers = numbers.extract! { |number| number.odd? } # => [1, 3, 5, 7, 9]
|
9
|
+
# numbers # => [0, 2, 4, 6, 8]
|
10
|
+
def extract!
|
11
|
+
return to_enum(:extract!) { size } unless block_given?
|
12
|
+
|
13
|
+
extracted_elements = []
|
14
|
+
|
15
|
+
reject! do |element|
|
16
|
+
extracted_elements << element if yield(element)
|
17
|
+
end
|
18
|
+
|
19
|
+
extracted_elements
|
20
|
+
end
|
21
|
+
end
|
@@ -1,8 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "active_support/core_ext/kernel/singleton_class"
|
4
3
|
require "active_support/core_ext/module/redefine_method"
|
5
|
-
require "active_support/core_ext/array/extract_options"
|
6
4
|
|
7
5
|
class Class
|
8
6
|
# Declare a class-level attribute whose value is inheritable by subclasses.
|
@@ -84,63 +82,50 @@ class Class
|
|
84
82
|
# To set a default value for the attribute, pass <tt>default:</tt>, like so:
|
85
83
|
#
|
86
84
|
# class_attribute :settings, default: {}
|
87
|
-
def class_attribute(*attrs
|
88
|
-
|
89
|
-
instance_reader = options.fetch(:instance_accessor, true) && options.fetch(:instance_reader, true)
|
90
|
-
instance_writer = options.fetch(:instance_accessor, true) && options.fetch(:instance_writer, true)
|
91
|
-
instance_predicate = options.fetch(:instance_predicate, true)
|
92
|
-
default_value = options.fetch(:default, nil)
|
85
|
+
def class_attribute(*attrs, instance_accessor: true,
|
86
|
+
instance_reader: instance_accessor, instance_writer: instance_accessor, instance_predicate: true, default: nil)
|
93
87
|
|
88
|
+
class_methods, methods = [], []
|
94
89
|
attrs.each do |name|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
singleton_class.silence_redefinition_of_method("#{name}?")
|
99
|
-
define_singleton_method("#{name}?") { !!public_send(name) } if instance_predicate
|
100
|
-
|
101
|
-
ivar = "@#{name}"
|
90
|
+
unless name.is_a?(Symbol) || name.is_a?(String)
|
91
|
+
raise TypeError, "#{name.inspect} is not a symbol nor a string"
|
92
|
+
end
|
102
93
|
|
103
|
-
|
104
|
-
|
105
|
-
singleton_class.class_eval do
|
106
|
-
redefine_method(name) { val }
|
94
|
+
class_methods << <<~RUBY # In case the method exists and is not public
|
95
|
+
silence_redefinition_of_method def #{name}
|
107
96
|
end
|
97
|
+
RUBY
|
108
98
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
if instance_variable_defined? ivar
|
113
|
-
instance_variable_get ivar
|
114
|
-
else
|
115
|
-
singleton_class.send name
|
116
|
-
end
|
117
|
-
end
|
118
|
-
end
|
99
|
+
methods << <<~RUBY if instance_reader
|
100
|
+
silence_redefinition_of_method def #{name}
|
101
|
+
defined?(@#{name}) ? @#{name} : self.class.#{name}
|
119
102
|
end
|
120
|
-
|
121
|
-
end
|
103
|
+
RUBY
|
122
104
|
|
123
|
-
|
124
|
-
|
125
|
-
if
|
126
|
-
|
127
|
-
|
128
|
-
self.class.public_send name
|
129
|
-
end
|
105
|
+
class_methods << <<~RUBY
|
106
|
+
silence_redefinition_of_method def #{name}=(value)
|
107
|
+
redefine_method(:#{name}) { value } if singleton_class?
|
108
|
+
redefine_singleton_method(:#{name}) { value }
|
109
|
+
value
|
130
110
|
end
|
111
|
+
RUBY
|
131
112
|
|
132
|
-
|
133
|
-
|
113
|
+
methods << <<~RUBY if instance_writer
|
114
|
+
silence_redefinition_of_method(:#{name}=)
|
115
|
+
attr_writer :#{name}
|
116
|
+
RUBY
|
134
117
|
|
135
|
-
if
|
136
|
-
|
137
|
-
|
118
|
+
if instance_predicate
|
119
|
+
class_methods << "silence_redefinition_of_method def #{name}?; !!self.#{name}; end"
|
120
|
+
if instance_reader
|
121
|
+
methods << "silence_redefinition_of_method def #{name}?; !!self.#{name}; end"
|
138
122
|
end
|
139
123
|
end
|
140
|
-
|
141
|
-
unless default_value.nil?
|
142
|
-
self.send("#{name}=", default_value)
|
143
|
-
end
|
144
124
|
end
|
125
|
+
|
126
|
+
location = caller_locations(1, 1).first
|
127
|
+
class_eval(["class << self", *class_methods, "end", *methods].join(";").tr("\n", ";"), location.path, location.lineno)
|
128
|
+
|
129
|
+
attrs.each { |name| public_send("#{name}=", default) }
|
145
130
|
end
|
146
131
|
end
|