diff options
Diffstat (limited to 'activesupport/lib')
27 files changed, 191 insertions, 64 deletions
diff --git a/activesupport/lib/active_support/cache.rb b/activesupport/lib/active_support/cache.rb index d769e2c8ea..8e516de4c9 100644 --- a/activesupport/lib/active_support/cache.rb +++ b/activesupport/lib/active_support/cache.rb @@ -229,6 +229,14 @@ module ActiveSupport # ask whether you should force a cache write. Otherwise, it's clearer to # just call <tt>Cache#write</tt>. # + # Setting <tt>skip_nil: true</tt> will not cache nil result: + # + # cache.fetch('foo') { nil } + # cache.fetch('bar', skip_nil: true) { nil } + # cache.exist?('foo') # => true + # cache.exist?('bar') # => false + # + # # Setting <tt>compress: false</tt> disables compression of the cache entry. # # Setting <tt>:expires_in</tt> will set an expiration time on the cache. @@ -695,7 +703,7 @@ module ActiveSupport yield(name) end - write(name, result, options) + write(name, result, options) unless result.nil? && options[:skip_nil] result end end diff --git a/activesupport/lib/active_support/cache/redis_cache_store.rb b/activesupport/lib/active_support/cache/redis_cache_store.rb index 11c574258f..5737450b4a 100644 --- a/activesupport/lib/active_support/cache/redis_cache_store.rb +++ b/activesupport/lib/active_support/cache/redis_cache_store.rb @@ -258,7 +258,14 @@ module ActiveSupport def increment(name, amount = 1, options = nil) instrument :increment, name, amount: amount do failsafe :increment do - redis.with { |c| c.incrby normalize_key(name, options), amount } + options = merged_options(options) + key = normalize_key(name, options) + + redis.with do |c| + c.incrby(key, amount).tap do + write_key_expiry(c, key, options) + end + end end end end @@ -274,7 +281,14 @@ module ActiveSupport def decrement(name, amount = 1, options = nil) instrument :decrement, name, amount: amount do failsafe :decrement do - redis.with { |c| c.decrby normalize_key(name, options), amount } + options = merged_options(options) + key = normalize_key(name, options) + + redis.with do |c| + c.decrby(key, amount).tap do + write_key_expiry(c, key, options) + end + end end end end @@ -385,6 +399,12 @@ module ActiveSupport end end + def write_key_expiry(client, key, options) + if options[:expires_in] && client.ttl(key).negative? + client.expire key, options[:expires_in].to_i + end + end + # Delete an entry from the cache. def delete_entry(key, options) failsafe :delete_entry, returning: false do diff --git a/activesupport/lib/active_support/callbacks.rb b/activesupport/lib/active_support/callbacks.rb index a1b841ec3d..c266b432c0 100644 --- a/activesupport/lib/active_support/callbacks.rb +++ b/activesupport/lib/active_support/callbacks.rb @@ -497,9 +497,7 @@ module ActiveSupport arg.halted || !@user_conditions.all? { |c| c.call(arg.target, arg.value) } end - def nested - @nested - end + attr_reader :nested def final? !@call_template @@ -578,7 +576,7 @@ module ActiveSupport end protected - def chain; @chain; end + attr_reader :chain private diff --git a/activesupport/lib/active_support/configurable.rb b/activesupport/lib/active_support/configurable.rb index 4d6f7819bb..2610114d8f 100644 --- a/activesupport/lib/active_support/configurable.rb +++ b/activesupport/lib/active_support/configurable.rb @@ -3,7 +3,6 @@ require "active_support/concern" require "active_support/ordered_options" require "active_support/core_ext/array/extract_options" -require "active_support/core_ext/regexp" module ActiveSupport # Configurable provides a <tt>config</tt> method to store and retrieve diff --git a/activesupport/lib/active_support/core_ext/module/attribute_accessors.rb b/activesupport/lib/active_support/core_ext/module/attribute_accessors.rb index 01fee0fb74..281eaa7d5f 100644 --- a/activesupport/lib/active_support/core_ext/module/attribute_accessors.rb +++ b/activesupport/lib/active_support/core_ext/module/attribute_accessors.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true require "active_support/core_ext/array/extract_options" -require "active_support/core_ext/regexp" # Extends the module object with class/module and instance accessors for # class/module attributes, just like the native attr* accessors for instance diff --git a/activesupport/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb b/activesupport/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb index 4b9b6ea9bd..b1788a000b 100644 --- a/activesupport/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +++ b/activesupport/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true require "active_support/core_ext/array/extract_options" -require "active_support/core_ext/regexp" # Extends the module object with class/module and instance accessors for # class/module attributes, just like the native attr* accessors for instance @@ -137,7 +136,7 @@ class Module # Or pass <tt>instance_accessor: false</tt>, to opt out both instance methods. # # class Current - # mattr_accessor :user, instance_accessor: false + # thread_mattr_accessor :user, instance_accessor: false # end # # Current.new.user = "DHH" # => NoMethodError diff --git a/activesupport/lib/active_support/core_ext/module/delegation.rb b/activesupport/lib/active_support/core_ext/module/delegation.rb index 7f42f44efb..3128539112 100644 --- a/activesupport/lib/active_support/core_ext/module/delegation.rb +++ b/activesupport/lib/active_support/core_ext/module/delegation.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true require "set" -require "active_support/core_ext/regexp" class Module # Error generated by +delegate+ when a method is called on +nil+ and +allow_nil+ diff --git a/activesupport/lib/active_support/core_ext/object/blank.rb b/activesupport/lib/active_support/core_ext/object/blank.rb index 2ca431ab10..ad6a9c6146 100644 --- a/activesupport/lib/active_support/core_ext/object/blank.rb +++ b/activesupport/lib/active_support/core_ext/object/blank.rb @@ -1,6 +1,5 @@ # frozen_string_literal: true -require "active_support/core_ext/regexp" require "concurrent/map" class Object diff --git a/activesupport/lib/active_support/core_ext/object/to_query.rb b/activesupport/lib/active_support/core_ext/object/to_query.rb index abb461966a..bac6ff9c97 100644 --- a/activesupport/lib/active_support/core_ext/object/to_query.rb +++ b/activesupport/lib/active_support/core_ext/object/to_query.rb @@ -75,11 +75,14 @@ class Hash # # This method is also aliased as +to_param+. def to_query(namespace = nil) - collect do |key, value| + query = collect do |key, value| unless (value.is_a?(Hash) || value.is_a?(Array)) && value.empty? value.to_query(namespace ? "#{namespace}[#{key}]" : key) end - end.compact.sort! * "&" + end.compact + + query.sort! unless namespace.to_s.include?("[]") + query.join("&") end alias_method :to_param, :to_query diff --git a/activesupport/lib/active_support/core_ext/object/with_options.rb b/activesupport/lib/active_support/core_ext/object/with_options.rb index 2838fd76be..1d46add6e0 100644 --- a/activesupport/lib/active_support/core_ext/object/with_options.rb +++ b/activesupport/lib/active_support/core_ext/object/with_options.rb @@ -68,7 +68,7 @@ class Object # You can access these methods using the class name instead: # # class Phone < ActiveRecord::Base - # enum phone_number_type: [home: 0, office: 1, mobile: 2] + # enum phone_number_type: { home: 0, office: 1, mobile: 2 } # # with_options presence: true do # validates :phone_number_type, inclusion: { in: Phone.phone_number_types.keys } diff --git a/activesupport/lib/active_support/dependencies.rb b/activesupport/lib/active_support/dependencies.rb index a02cefc78e..9dc2c46880 100644 --- a/activesupport/lib/active_support/dependencies.rb +++ b/activesupport/lib/active_support/dependencies.rb @@ -345,7 +345,7 @@ module ActiveSupport #:nodoc: end def require_or_load(file_name, const_path = nil) - file_name = $` if file_name =~ /\.rb\z/ + file_name = file_name.chomp(".rb") expanded = File.expand_path(file_name) return if loaded.include?(expanded) @@ -395,7 +395,7 @@ module ActiveSupport #:nodoc: # constant paths which would cause Dependencies to attempt to load this # file. def loadable_constants_for_path(path, bases = autoload_paths) - path = $` if path =~ /\.rb\z/ + path = path.chomp(".rb") expanded_path = File.expand_path(path) paths = [] diff --git a/activesupport/lib/active_support/deprecation/method_wrappers.rb b/activesupport/lib/active_support/deprecation/method_wrappers.rb index 5be893d281..81482092fe 100644 --- a/activesupport/lib/active_support/deprecation/method_wrappers.rb +++ b/activesupport/lib/active_support/deprecation/method_wrappers.rb @@ -1,6 +1,5 @@ # frozen_string_literal: true -require "active_support/core_ext/module/aliasing" require "active_support/core_ext/array/extract_options" module ActiveSupport @@ -54,23 +53,26 @@ module ActiveSupport deprecator = options.delete(:deprecator) || self method_names += options.keys - mod = Module.new do - method_names.each do |method_name| - define_method(method_name) do |*args, &block| - deprecator.deprecation_warning(method_name, options[method_name]) - super(*args, &block) - end + method_names.each do |method_name| + aliased_method, punctuation = method_name.to_s.sub(/([?!=])$/, ""), $1 + with_method = "#{aliased_method}_with_deprecation#{punctuation}" + without_method = "#{aliased_method}_without_deprecation#{punctuation}" - case - when target_module.protected_method_defined?(method_name) - protected method_name - when target_module.private_method_defined?(method_name) - private method_name - end + target_module.send(:define_method, with_method) do |*args, &block| + deprecator.deprecation_warning(method_name, options[method_name]) + send(without_method, *args, &block) end - end - target_module.prepend(mod) + target_module.send(:alias_method, without_method, method_name) + target_module.send(:alias_method, method_name, with_method) + + case + when target_module.protected_method_defined?(without_method) + target_module.send(:protected, method_name) + when target_module.private_method_defined?(without_method) + target_module.send(:private, method_name) + end + end end end end diff --git a/activesupport/lib/active_support/deprecation/proxy_wrappers.rb b/activesupport/lib/active_support/deprecation/proxy_wrappers.rb index 896c0d2d8e..56f1e23136 100644 --- a/activesupport/lib/active_support/deprecation/proxy_wrappers.rb +++ b/activesupport/lib/active_support/deprecation/proxy_wrappers.rb @@ -1,7 +1,5 @@ # frozen_string_literal: true -require "active_support/core_ext/regexp" - module ActiveSupport class Deprecation class DeprecationProxy #:nodoc: diff --git a/activesupport/lib/active_support/duration/iso8601_parser.rb b/activesupport/lib/active_support/duration/iso8601_parser.rb index 1847eeaa86..414f727705 100644 --- a/activesupport/lib/active_support/duration/iso8601_parser.rb +++ b/activesupport/lib/active_support/duration/iso8601_parser.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true require "strscan" -require "active_support/core_ext/regexp" module ActiveSupport class Duration diff --git a/activesupport/lib/active_support/inflector/inflections.rb b/activesupport/lib/active_support/inflector/inflections.rb index 7e5dff1d6d..2b86d233e5 100644 --- a/activesupport/lib/active_support/inflector/inflections.rb +++ b/activesupport/lib/active_support/inflector/inflections.rb @@ -2,7 +2,6 @@ require "concurrent/map" require "active_support/core_ext/array/prepend_and_append" -require "active_support/core_ext/regexp" require "active_support/i18n" require "active_support/deprecation" diff --git a/activesupport/lib/active_support/inflector/methods.rb b/activesupport/lib/active_support/inflector/methods.rb index 339b93b8da..7359de762a 100644 --- a/activesupport/lib/active_support/inflector/methods.rb +++ b/activesupport/lib/active_support/inflector/methods.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true require "active_support/inflections" -require "active_support/core_ext/regexp" module ActiveSupport # The Inflector transforms words from singular to plural, class names to table diff --git a/activesupport/lib/active_support/key_generator.rb b/activesupport/lib/active_support/key_generator.rb index 78f7d7ca8d..00edcdd05a 100644 --- a/activesupport/lib/active_support/key_generator.rb +++ b/activesupport/lib/active_support/key_generator.rb @@ -59,7 +59,7 @@ module ActiveSupport if secret.blank? raise ArgumentError, "A secret is required to generate an integrity hash " \ "for cookie session data. Set a secret_key_base of at least " \ - "#{SECRET_MIN_LENGTH} characters in via `bin/rails credentials:edit`." + "#{SECRET_MIN_LENGTH} characters by running `rails credentials:edit`." end if secret.length < SECRET_MIN_LENGTH diff --git a/activesupport/lib/active_support/lazy_load_hooks.rb b/activesupport/lib/active_support/lazy_load_hooks.rb index dc8080c469..a6b096a973 100644 --- a/activesupport/lib/active_support/lazy_load_hooks.rb +++ b/activesupport/lib/active_support/lazy_load_hooks.rb @@ -68,7 +68,11 @@ module ActiveSupport if options[:yield] block.call(base) else - base.instance_eval(&block) + if base.is_a?(Module) + base.class_eval(&block) + else + base.instance_eval(&block) + end end end end diff --git a/activesupport/lib/active_support/message_encryptor.rb b/activesupport/lib/active_support/message_encryptor.rb index 8b73270894..404404cad1 100644 --- a/activesupport/lib/active_support/message_encryptor.rb +++ b/activesupport/lib/active_support/message_encryptor.rb @@ -210,9 +210,7 @@ module ActiveSupport OpenSSL::Cipher.new(@cipher) end - def verifier - @verifier - end + attr_reader :verifier def aead_mode? @aead_mode ||= new_cipher.authenticated? diff --git a/activesupport/lib/active_support/multibyte/chars.rb b/activesupport/lib/active_support/multibyte/chars.rb index 8152b8fd22..499a206f49 100644 --- a/activesupport/lib/active_support/multibyte/chars.rb +++ b/activesupport/lib/active_support/multibyte/chars.rb @@ -4,7 +4,6 @@ require "active_support/json" require "active_support/core_ext/string/access" require "active_support/core_ext/string/behavior" require "active_support/core_ext/module/delegation" -require "active_support/core_ext/regexp" module ActiveSupport #:nodoc: module Multibyte #:nodoc: diff --git a/activesupport/lib/active_support/notifications/fanout.rb b/activesupport/lib/active_support/notifications/fanout.rb index 25aab175b4..4e4ca70942 100644 --- a/activesupport/lib/active_support/notifications/fanout.rb +++ b/activesupport/lib/active_support/notifications/fanout.rb @@ -70,12 +70,29 @@ module ActiveSupport module Subscribers # :nodoc: def self.new(pattern, listener) + subscriber_class = Timed + if listener.respond_to?(:start) && listener.respond_to?(:finish) - subscriber = Evented.new pattern, listener + subscriber_class = Evented else - subscriber = Timed.new pattern, listener + # Doing all this to detect a block like `proc { |x| }` vs + # `proc { |*x| }` or `proc { |**x| }` + if listener.respond_to?(:parameters) + params = listener.parameters + if params.length == 1 && params.first.first == :opt + subscriber_class = EventObject + end + end end + wrap_all pattern, subscriber_class.new(pattern, listener) + end + + def self.event_object_subscriber(pattern, block) + wrap_all pattern, EventObject.new(pattern, block) + end + + def self.wrap_all(pattern, subscriber) unless pattern AllMessages.new(subscriber) else @@ -130,6 +147,27 @@ module ActiveSupport end end + class EventObject < Evented + def start(name, id, payload) + stack = Thread.current[:_event_stack] ||= [] + event = build_event name, id, payload + event.start! + stack.push event + end + + def finish(name, id, payload) + stack = Thread.current[:_event_stack] + event = stack.pop + event.finish! + @delegate.call event + end + + private + def build_event(name, id, payload) + ActiveSupport::Notifications::Event.new name, nil, nil, id, payload + end + end + class AllMessages # :nodoc: def initialize(delegate) @delegate = delegate diff --git a/activesupport/lib/active_support/notifications/instrumenter.rb b/activesupport/lib/active_support/notifications/instrumenter.rb index e99f5ee688..f8344912bb 100644 --- a/activesupport/lib/active_support/notifications/instrumenter.rb +++ b/activesupport/lib/active_support/notifications/instrumenter.rb @@ -63,6 +63,42 @@ module ActiveSupport @end = ending @children = [] @duration = nil + @cpu_time_start = nil + @cpu_time_finish = nil + @allocation_count_start = 0 + @allocation_count_finish = 0 + end + + # Record information at the time this event starts + def start! + @time = now + @cpu_time_start = now_cpu + @allocation_count_start = now_allocations + end + + # Record information at the time this event finishes + def finish! + @cpu_time_finish = now_cpu + @end = now + @allocation_count_finish = now_allocations + end + + # Returns the CPU time (in milliseconds) passed since the call to + # +start!+ and the call to +finish!+ + def cpu_time + (@cpu_time_finish - @cpu_time_start) * 1000 + end + + # Returns the idle time time (in milliseconds) passed since the call to + # +start!+ and the call to +finish!+ + def idle_time + duration - cpu_time + end + + # Returns the number of allocations made since the call to +start!+ and + # the call to +finish!+ + def allocations + @allocation_count_finish - @allocation_count_start end # Returns the difference in milliseconds between when the execution of the @@ -88,6 +124,31 @@ module ActiveSupport def parent_of?(event) @children.include? event end + + private + def now + Process.clock_gettime(Process::CLOCK_MONOTONIC) + end + + if defined?(Process::CLOCK_PROCESS_CPUTIME_ID) + def now_cpu + Process.clock_gettime(Process::CLOCK_PROCESS_CPUTIME_ID) + end + else + def now_cpu + 0 + end + end + + if defined?(JRUBY_VERSION) + def now_allocations + 0 + end + else + def now_allocations + GC.stat :total_allocated_objects + end + end end end end diff --git a/activesupport/lib/active_support/subscriber.rb b/activesupport/lib/active_support/subscriber.rb index 8ad39f7a05..5a4c3d74af 100644 --- a/activesupport/lib/active_support/subscriber.rb +++ b/activesupport/lib/active_support/subscriber.rb @@ -79,7 +79,8 @@ module ActiveSupport end def start(name, id, payload) - e = ActiveSupport::Notifications::Event.new(name, Time.now, nil, id, payload) + e = ActiveSupport::Notifications::Event.new(name, nil, nil, id, payload) + e.start! parent = event_stack.last parent << e if parent @@ -87,9 +88,8 @@ module ActiveSupport end def finish(name, id, payload) - finished = Time.now - event = event_stack.pop - event.end = finished + event = event_stack.pop + event.finish! event.payload.merge!(payload) method = name.split(".".freeze).first @@ -97,7 +97,6 @@ module ActiveSupport end private - def event_stack SubscriberQueueRegistry.instance.get_queue(@queue_key) end diff --git a/activesupport/lib/active_support/testing/assertions.rb b/activesupport/lib/active_support/testing/assertions.rb index 6a56da384f..b27ac7ce99 100644 --- a/activesupport/lib/active_support/testing/assertions.rb +++ b/activesupport/lib/active_support/testing/assertions.rb @@ -113,11 +113,23 @@ module ActiveSupport # post :create, params: { article: invalid_attributes } # end # + # A lambda can be passed in and evaluated. + # + # assert_no_difference -> { Article.count } do + # post :create, params: { article: invalid_attributes } + # end + # # An error message can be specified. # # assert_no_difference 'Article.count', 'An Article should not be created' do # post :create, params: { article: invalid_attributes } # end + # + # An array of expressions can also be passed in and evaluated. + # + # assert_no_difference [ 'Article.count', -> { Post.count } ] do + # post :create, params: { article: invalid_attributes } + # end def assert_no_difference(expression, message = nil, &block) assert_difference expression, 0, message, &block end diff --git a/activesupport/lib/active_support/testing/deprecation.rb b/activesupport/lib/active_support/testing/deprecation.rb index f655435729..18d63d2780 100644 --- a/activesupport/lib/active_support/testing/deprecation.rb +++ b/activesupport/lib/active_support/testing/deprecation.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true require "active_support/deprecation" -require "active_support/core_ext/regexp" module ActiveSupport module Testing diff --git a/activesupport/lib/active_support/testing/parallelization.rb b/activesupport/lib/active_support/testing/parallelization.rb index 59c8486f41..1caac1feb3 100644 --- a/activesupport/lib/active_support/testing/parallelization.rb +++ b/activesupport/lib/active_support/testing/parallelization.rb @@ -26,25 +26,21 @@ module ActiveSupport def pop; @queue.pop; end end - @after_fork_hooks = [] + @@after_fork_hooks = [] def self.after_fork_hook(&blk) - @after_fork_hooks << blk + @@after_fork_hooks << blk end - def self.after_fork_hooks - @after_fork_hooks - end + cattr_reader :after_fork_hooks - @run_cleanup_hooks = [] + @@run_cleanup_hooks = [] def self.run_cleanup_hook(&blk) - @run_cleanup_hooks << blk + @@run_cleanup_hooks << blk end - def self.run_cleanup_hooks - @run_cleanup_hooks - end + cattr_reader :run_cleanup_hooks def initialize(queue_size) @queue_size = queue_size diff --git a/activesupport/lib/active_support/values/time_zone.rb b/activesupport/lib/active_support/values/time_zone.rb index 792c88415c..fd07a3a6a2 100644 --- a/activesupport/lib/active_support/values/time_zone.rb +++ b/activesupport/lib/active_support/values/time_zone.rb @@ -265,7 +265,7 @@ module ActiveSupport private def load_country_zones(code) country = TZInfo::Country.get(code) - country.zone_identifiers.map do |tz_id| + country.zone_identifiers.flat_map do |tz_id| if MAPPING.value?(tz_id) MAPPING.inject([]) do |memo, (key, value)| memo << self[key] if value == tz_id @@ -274,7 +274,7 @@ module ActiveSupport else create(tz_id, nil, TZInfo::Timezone.new(tz_id)) end - end.flatten(1).sort! + end.sort! end def zones_map |