diff options
Diffstat (limited to 'activesupport/lib')
18 files changed, 154 insertions, 114 deletions
diff --git a/activesupport/lib/active_support.rb b/activesupport/lib/active_support.rb index 2019afeb00..94fe893149 100644 --- a/activesupport/lib/active_support.rb +++ b/activesupport/lib/active_support.rb @@ -1,5 +1,5 @@ #-- -# Copyright (c) 2005-2015 David Heinemeier Hansson +# Copyright (c) 2005-2016 David Heinemeier Hansson # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the diff --git a/activesupport/lib/active_support/cache.rb b/activesupport/lib/active_support/cache.rb index 8272d3395c..610105f41c 100644 --- a/activesupport/lib/active_support/cache.rb +++ b/activesupport/lib/active_support/cache.rb @@ -255,10 +255,11 @@ module ActiveSupport # end # end # - # # val_1 => "new value 1" - # # val_2 => "original value" - # # sleep 10 # First thread extend the life of cache by another 10 seconds - # # cache.fetch('foo') => "new value 1" + # cache.fetch('foo') # => "original value" + # sleep 10 # First thread extended the life of cache by another 10 seconds + # cache.fetch('foo') # => "new value 1" + # val_1 # => "new value 1" + # val_2 # => "original value" # # Other options will be handled by the specific cache store implementation. # Internally, #fetch calls #read_entry, and calls #write_entry on a cache diff --git a/activesupport/lib/active_support/cache/file_store.rb b/activesupport/lib/active_support/cache/file_store.rb index dff2443bc8..99c55b1aa4 100644 --- a/activesupport/lib/active_support/cache/file_store.rb +++ b/activesupport/lib/active_support/cache/file_store.rb @@ -17,6 +17,7 @@ module ActiveSupport FILENAME_MAX_SIZE = 228 # max filename size on file system is 255, minus room for timestamp and random characters appended by Tempfile (used by atomic write) FILEPATH_MAX_SIZE = 900 # max is 1024, plus some room EXCLUDED_DIRS = ['.', '..'].freeze + GITKEEP_FILES = ['.gitkeep', '.keep'].freeze def initialize(cache_path, options = nil) super(options) @@ -24,10 +25,10 @@ module ActiveSupport end # Deletes all items from the cache. In this case it deletes all the entries in the specified - # file store directory except for .gitkeep. Be careful which directory is specified in your + # file store directory except for .keep or .gitkeep. Be careful which directory is specified in your # config file when using +FileStore+ because everything in that directory will be deleted. def clear(options = nil) - root_dirs = Dir.entries(cache_path).reject {|f| (EXCLUDED_DIRS + [".gitkeep"]).include?(f)} + root_dirs = exclude_from(cache_path, EXCLUDED_DIRS + GITKEEP_FILES) FileUtils.rm_r(root_dirs.collect{|f| File.join(cache_path, f)}) rescue Errno::ENOENT end @@ -154,7 +155,7 @@ module ActiveSupport # Delete empty directories in the cache. def delete_empty_directories(dir) return if File.realpath(dir) == File.realpath(cache_path) - if Dir.entries(dir).reject {|f| EXCLUDED_DIRS.include?(f)}.empty? + if exclude_from(dir, EXCLUDED_DIRS).empty? Dir.delete(dir) rescue nil delete_empty_directories(File.dirname(dir)) end @@ -193,6 +194,11 @@ module ActiveSupport end end end + + # Exclude entries from source directory + def exclude_from(source, excludes) + Dir.entries(source).reject { |f| excludes.include?(f) } + end end end end 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 124f90dc0f..76825862d7 100644 --- a/activesupport/lib/active_support/core_ext/module/attribute_accessors.rb +++ b/activesupport/lib/active_support/core_ext/module/attribute_accessors.rb @@ -49,7 +49,7 @@ class Module # include HairColors # end # - # Person.hair_colors # => [:brown, :black, :blonde, :red] + # Person.new.hair_colors # => [:brown, :black, :blonde, :red] def mattr_reader(*syms) options = syms.extract_options! syms.each do |sym| @@ -105,7 +105,7 @@ class Module # # Also, you can pass a block to set up the attribute with a default value. # - # class HairColors + # module HairColors # mattr_writer :hair_colors do # [:brown, :black, :blonde, :red] # end @@ -150,8 +150,8 @@ class Module # include HairColors # end # - # Person.hair_colors = [:brown, :black, :blonde, :red] - # Person.hair_colors # => [:brown, :black, :blonde, :red] + # HairColors.hair_colors = [:brown, :black, :blonde, :red] + # HairColors.hair_colors # => [:brown, :black, :blonde, :red] # Person.new.hair_colors # => [:brown, :black, :blonde, :red] # # If a subclass changes the value then that would also change the value for @@ -161,8 +161,8 @@ class Module # class Male < Person # end # - # Male.hair_colors << :blue - # Person.hair_colors # => [:brown, :black, :blonde, :red, :blue] + # Male.new.hair_colors << :blue + # Person.new.hair_colors # => [:brown, :black, :blonde, :red, :blue] # # To opt out of the instance writer method, pass <tt>instance_writer: false</tt>. # To opt out of the instance reader method, pass <tt>instance_reader: false</tt>. diff --git a/activesupport/lib/active_support/core_ext/numeric/conversions.rb b/activesupport/lib/active_support/core_ext/numeric/conversions.rb index 9a3651f29a..9d832897ed 100644 --- a/activesupport/lib/active_support/core_ext/numeric/conversions.rb +++ b/activesupport/lib/active_support/core_ext/numeric/conversions.rb @@ -1,5 +1,6 @@ require 'active_support/core_ext/big_decimal/conversions' require 'active_support/number_helper' +require 'active_support/core_ext/module/deprecation' module ActiveSupport::NumericWithFormat @@ -75,6 +76,8 @@ module ActiveSupport::NumericWithFormat # 1234567.to_s(:human_size) # => 1.18 MB # 1234567890.to_s(:human_size) # => 1.15 GB # 1234567890123.to_s(:human_size) # => 1.12 TB + # 1234567890123456.to_s(:human_size) # => 1.1 PB + # 1234567890123456789.to_s(:human_size) # => 1.07 EB # 1234567.to_s(:human_size, precision: 2) # => 1.2 MB # 483989.to_s(:human_size, precision: 2) # => 470 KB # 1234567.to_s(:human_size, precision: 2, separator: ',') # => 1,2 MB @@ -117,7 +120,11 @@ module ActiveSupport::NumericWithFormat when :human_size return ActiveSupport::NumberHelper.number_to_human_size(self, options) else - super + if is_a?(Float) || format.is_a?(Symbol) + super() + else + super + end end end diff --git a/activesupport/lib/active_support/core_ext/string/output_safety.rb b/activesupport/lib/active_support/core_ext/string/output_safety.rb index 510fa48189..04ed8e7cd8 100644 --- a/activesupport/lib/active_support/core_ext/string/output_safety.rb +++ b/activesupport/lib/active_support/core_ext/string/output_safety.rb @@ -5,7 +5,6 @@ class ERB module Util HTML_ESCAPE = { '&' => '&', '>' => '>', '<' => '<', '"' => '"', "'" => ''' } JSON_ESCAPE = { '&' => '\u0026', '>' => '\u003e', '<' => '\u003c', "\u2028" => '\u2028', "\u2029" => '\u2029' } - HTML_ESCAPE_REGEXP = /[&"'><]/ HTML_ESCAPE_ONCE_REGEXP = /["><']|&(?!([a-zA-Z]+|(#\d+)|(#[xX][\dA-Fa-f]+));)/ JSON_ESCAPE_REGEXP = /[\u2028\u2029&><]/u @@ -37,7 +36,7 @@ class ERB if s.html_safe? s else - ActiveSupport::Multibyte::Unicode.tidy_bytes(s).gsub(HTML_ESCAPE_REGEXP, HTML_ESCAPE) + CGI.escapeHTML(ActiveSupport::Multibyte::Unicode.tidy_bytes(s)) end end module_function :unwrapped_html_escape @@ -243,8 +242,7 @@ module ActiveSupport #:nodoc: private def html_escape_interpolated_argument(arg) - (!html_safe? || arg.html_safe?) ? arg : - arg.to_s.gsub(ERB::Util::HTML_ESCAPE_REGEXP, ERB::Util::HTML_ESCAPE) + (!html_safe? || arg.html_safe?) ? arg : CGI.escapeHTML(arg.to_s) end end end diff --git a/activesupport/lib/active_support/deprecation/method_wrappers.rb b/activesupport/lib/active_support/deprecation/method_wrappers.rb index 32fe8025fe..f5ea6669ce 100644 --- a/activesupport/lib/active_support/deprecation/method_wrappers.rb +++ b/activesupport/lib/active_support/deprecation/method_wrappers.rb @@ -21,15 +21,15 @@ module ActiveSupport # # => [:aaa, :bbb, :ccc] # # Fred.aaa - # # DEPRECATION WARNING: aaa is deprecated and will be removed from Rails 5.0. (called from irb_binding at (irb):10) + # # DEPRECATION WARNING: aaa is deprecated and will be removed from Rails 5.1. (called from irb_binding at (irb):10) # # => nil # # Fred.bbb - # # DEPRECATION WARNING: bbb is deprecated and will be removed from Rails 5.0 (use zzz instead). (called from irb_binding at (irb):11) + # # DEPRECATION WARNING: bbb is deprecated and will be removed from Rails 5.1 (use zzz instead). (called from irb_binding at (irb):11) # # => nil # # Fred.ccc - # # DEPRECATION WARNING: ccc is deprecated and will be removed from Rails 5.0 (use Bar#ccc instead). (called from irb_binding at (irb):12) + # # DEPRECATION WARNING: ccc is deprecated and will be removed from Rails 5.1 (use Bar#ccc instead). (called from irb_binding at (irb):12) # # => nil # # Passing in a custom deprecator: diff --git a/activesupport/lib/active_support/hash_with_indifferent_access.rb b/activesupport/lib/active_support/hash_with_indifferent_access.rb index 4ff35a45a1..b878f31e75 100644 --- a/activesupport/lib/active_support/hash_with_indifferent_access.rb +++ b/activesupport/lib/active_support/hash_with_indifferent_access.rb @@ -68,12 +68,10 @@ module ActiveSupport end end - def default(key = nil) - if key.is_a?(Symbol) && include?(key = key.to_s) - self[key] - else - super - end + def default(*args) + key = args.first + args[0] = key.to_s if key.is_a?(Symbol) + super(*args) end def self.new_from_hash_copying_default(hash) @@ -159,6 +157,20 @@ module ActiveSupport alias_method :has_key?, :key? alias_method :member?, :key? + + # Same as <tt>Hash#[]</tt> where the key passed as argument can be + # either a string or a symbol: + # + # counters = ActiveSupport::HashWithIndifferentAccess.new + # counters[:foo] = 1 + # + # counters['foo'] # => 1 + # counters[:foo] # => 1 + # counters[:zoo] # => nil + def [](key) + super(convert_key(key)) + end + # Same as <tt>Hash#fetch</tt> where the key passed as argument can be # either a string or a symbol: # diff --git a/activesupport/lib/active_support/inflector/methods.rb b/activesupport/lib/active_support/inflector/methods.rb index 595b0339cc..f741c0bfb8 100644 --- a/activesupport/lib/active_support/inflector/methods.rb +++ b/activesupport/lib/active_support/inflector/methods.rb @@ -173,7 +173,7 @@ module ActiveSupport # # Singular names are not handled correctly: # - # classify('calculus') # => "Calculu" + # classify('calculus') # => "Calculus" def classify(table_name) # strip out any leading schema name camelize(singularize(table_name.to_s.sub(/.*\./, ''.freeze))) diff --git a/activesupport/lib/active_support/locale/en.yml b/activesupport/lib/active_support/locale/en.yml index a4563ace8f..c64b7598ee 100644 --- a/activesupport/lib/active_support/locale/en.yml +++ b/activesupport/lib/active_support/locale/en.yml @@ -106,6 +106,8 @@ en: mb: "MB" gb: "GB" tb: "TB" + pb: "PB" + eb: "EB" # Used in NumberHelper.number_to_human() decimal_units: format: "%n %u" diff --git a/activesupport/lib/active_support/logger.rb b/activesupport/lib/active_support/logger.rb index 82117a64d2..7626b28108 100644 --- a/activesupport/lib/active_support/logger.rb +++ b/activesupport/lib/active_support/logger.rb @@ -5,18 +5,27 @@ module ActiveSupport class Logger < ::Logger include LoggerSilence - attr_accessor :broadcast_messages + # Returns true if the logger destination matches one of the sources + # + # logger = Logger.new(STDOUT) + # ActiveSupport::Logger.logger_outputs_to?(logger, STDOUT) + # # => true + def self.logger_outputs_to?(logger, *sources) + logdev = logger.instance_variable_get("@logdev") + logger_source = logdev.dev if logdev.respond_to?(:dev) + sources.any? { |source| source == logger_source } + end # Broadcasts logs to multiple loggers. def self.broadcast(logger) # :nodoc: Module.new do define_method(:add) do |*args, &block| - logger.add(*args, &block) if broadcast_messages + logger.add(*args, &block) super(*args, &block) end define_method(:<<) do |x| - logger << x if broadcast_messages + logger << x super(x) end @@ -45,7 +54,20 @@ module ActiveSupport def initialize(*args) super @formatter = SimpleFormatter.new - @broadcast_messages = true + after_initialize if respond_to? :after_initialize + end + + def add(severity, message = nil, progname = nil, &block) + return true if @logdev.nil? || (severity || UNKNOWN) < level + super + end + + Logger::Severity.constants.each do |severity| + class_eval(<<-EOT, __FILE__, __LINE__ + 1) + def #{severity.downcase}? # def debug? + Logger::#{severity} >= level # DEBUG >= level + end # end + EOT end # Simple formatter which only displays the message. diff --git a/activesupport/lib/active_support/logger_silence.rb b/activesupport/lib/active_support/logger_silence.rb index 7d92256f24..125d81d973 100644 --- a/activesupport/lib/active_support/logger_silence.rb +++ b/activesupport/lib/active_support/logger_silence.rb @@ -1,25 +1,45 @@ require 'active_support/concern' require 'active_support/core_ext/module/attribute_accessors' +require 'concurrent' module LoggerSilence extend ActiveSupport::Concern included do cattr_accessor :silencer + attr_reader :local_levels self.silencer = true end + def after_initialize + @local_levels = Concurrent::Map.new(:initial_capacity => 2) + end + + def local_log_id + Thread.current.__id__ + end + + def level + local_levels[local_log_id] || super + end + # Silences the logger for the duration of the block. def silence(temporary_level = Logger::ERROR) if silencer begin - old_logger_level, self.level = level, temporary_level + old_local_level = local_levels[local_log_id] + local_levels[local_log_id] = temporary_level + yield self ensure - self.level = old_logger_level + if old_local_level + local_levels[local_log_id] = old_local_level + else + local_levels.delete(local_log_id) + end end else yield self end end -end +end
\ No newline at end of file diff --git a/activesupport/lib/active_support/multibyte/unicode.rb b/activesupport/lib/active_support/multibyte/unicode.rb index 586002b03b..72b20fff06 100644 --- a/activesupport/lib/active_support/multibyte/unicode.rb +++ b/activesupport/lib/active_support/multibyte/unicode.rb @@ -87,19 +87,44 @@ module ActiveSupport pos += 1 previous = codepoints[pos-1] current = codepoints[pos] - if ( - # CR X LF - ( previous == database.boundary[:cr] and current == database.boundary[:lf] ) or - # L X (L|V|LV|LVT) - ( database.boundary[:l] === previous and in_char_class?(current, [:l,:v,:lv,:lvt]) ) or - # (LV|V) X (V|T) - ( in_char_class?(previous, [:lv,:v]) and in_char_class?(current, [:v,:t]) ) or - # (LVT|T) X (T) - ( in_char_class?(previous, [:lvt,:t]) and database.boundary[:t] === current ) or - # X Extend - (database.boundary[:extend] === current) - ) - else + + should_break = + # GB3. CR X LF + if previous == database.boundary[:cr] and current == database.boundary[:lf] + false + # GB4. (Control|CR|LF) ÷ + elsif previous and in_char_class?(previous, [:control,:cr,:lf]) + true + # GB5. ÷ (Control|CR|LF) + elsif in_char_class?(current, [:control,:cr,:lf]) + true + # GB6. L X (L|V|LV|LVT) + elsif database.boundary[:l] === previous and in_char_class?(current, [:l,:v,:lv,:lvt]) + false + # GB7. (LV|V) X (V|T) + elsif in_char_class?(previous, [:lv,:v]) and in_char_class?(current, [:v,:t]) + false + # GB8. (LVT|T) X (T) + elsif in_char_class?(previous, [:lvt,:t]) and database.boundary[:t] === current + false + # GB8a. Regional_Indicator X Regional_Indicator + elsif database.boundary[:regional_indicator] === previous and database.boundary[:regional_indicator] === current + false + # GB9. X Extend + elsif database.boundary[:extend] === current + false + # GB9a. X SpacingMark + elsif database.boundary[:spacingmark] === current + false + # GB9b. Prepend X + elsif database.boundary[:prepend] === previous + false + # GB10. Any ÷ Any + else + true + end + + if should_break unpacked << codepoints[marker..pos-1] marker = pos end diff --git a/activesupport/lib/active_support/notifications/instrumenter.rb b/activesupport/lib/active_support/notifications/instrumenter.rb index 67f2ee1a7f..91f94cb2d7 100644 --- a/activesupport/lib/active_support/notifications/instrumenter.rb +++ b/activesupport/lib/active_support/notifications/instrumenter.rb @@ -21,6 +21,7 @@ module ActiveSupport yield payload rescue Exception => e payload[:exception] = [e.class.name, e.message] + payload[:exception_object] = e raise e ensure finish_with_state listeners_state, name, payload diff --git a/activesupport/lib/active_support/number_helper.rb b/activesupport/lib/active_support/number_helper.rb index 248521e677..64d9e71f37 100644 --- a/activesupport/lib/active_support/number_helper.rb +++ b/activesupport/lib/active_support/number_helper.rb @@ -47,6 +47,14 @@ module ActiveSupport # Formats a +number+ into a currency string (e.g., $13.65). You # can customize the format in the +options+ hash. # + # The currency unit and number formatting of the current locale will be used + # unless otherwise specified in the provided options. No currency conversion + # is performed. If the user is given a way to change their locale, they will + # also be able to change the relative value of the currency displayed with + # this helper. If your application will ever support multiple locales, you + # may want to specify a constant <tt>:locale</tt> option or consider + # using a library capable of currency conversion. + # # ==== Options # # * <tt>:locale</tt> - Sets the locale to be used for formatting @@ -235,6 +243,8 @@ module ActiveSupport # number_to_human_size(1234567) # => 1.18 MB # number_to_human_size(1234567890) # => 1.15 GB # number_to_human_size(1234567890123) # => 1.12 TB + # number_to_human_size(1234567890123456) # => 1.1 PB + # number_to_human_size(1234567890123456789) # => 1.07 EB # number_to_human_size(1234567, precision: 2) # => 1.2 MB # number_to_human_size(483989, precision: 2) # => 470 KB # number_to_human_size(1234567, precision: 2, separator: ',') # => 1,2 MB diff --git a/activesupport/lib/active_support/number_helper/number_to_human_size_converter.rb b/activesupport/lib/active_support/number_helper/number_to_human_size_converter.rb index a4a8690bcd..a83b368b7f 100644 --- a/activesupport/lib/active_support/number_helper/number_to_human_size_converter.rb +++ b/activesupport/lib/active_support/number_helper/number_to_human_size_converter.rb @@ -1,7 +1,7 @@ module ActiveSupport module NumberHelper class NumberToHumanSizeConverter < NumberConverter #:nodoc: - STORAGE_UNITS = [:byte, :kb, :mb, :gb, :tb] + STORAGE_UNITS = [:byte, :kb, :mb, :gb, :tb, :pb, :eb] self.namespace = :human self.validate_float = true diff --git a/activesupport/lib/active_support/test_case.rb b/activesupport/lib/active_support/test_case.rb index ae6f00b861..d9a668c0ea 100644 --- a/activesupport/lib/active_support/test_case.rb +++ b/activesupport/lib/active_support/test_case.rb @@ -9,7 +9,6 @@ require 'active_support/testing/isolation' require 'active_support/testing/constant_lookup' require 'active_support/testing/time_helpers' require 'active_support/testing/file_fixtures' -require 'active_support/testing/composite_filter' require 'active_support/core_ext/kernel/reporting' module ActiveSupport @@ -39,15 +38,6 @@ module ActiveSupport def test_order ActiveSupport.test_order ||= :random end - - def run(reporter, options = {}) - if options[:patterns] && options[:patterns].any? { |p| p =~ /:\d+/ } - options[:filter] = \ - Testing::CompositeFilter.new(self, options[:filter], options[:patterns]) - end - - super - end end alias_method :method_name, :name diff --git a/activesupport/lib/active_support/testing/composite_filter.rb b/activesupport/lib/active_support/testing/composite_filter.rb deleted file mode 100644 index bde723e30b..0000000000 --- a/activesupport/lib/active_support/testing/composite_filter.rb +++ /dev/null @@ -1,54 +0,0 @@ -require 'method_source' - -module ActiveSupport - module Testing - class CompositeFilter # :nodoc: - def initialize(runnable, filter, patterns) - @runnable = runnable - @filters = [ derive_regexp(filter), *derive_line_filters(patterns) ].compact - end - - def ===(method) - @filters.any? { |filter| filter === method } - end - - private - def derive_regexp(filter) - filter =~ %r%/(.*)/% ? Regexp.new($1) : filter - end - - def derive_line_filters(patterns) - patterns.map do |file_and_line| - file, line = file_and_line.split(':') - Filter.new(@runnable, file, line) if file - end - end - - class Filter # :nodoc: - def initialize(runnable, file, line) - @runnable, @file = runnable, File.expand_path(file) - @line = line.to_i if line - end - - def ===(method) - return unless @runnable.method_defined?(method) - - if @line - test_file, test_range = definition_for(@runnable.instance_method(method)) - test_file == @file && test_range.include?(@line) - else - @runnable.instance_method(method).source_location.first == @file - end - end - - private - def definition_for(method) - file, start_line = method.source_location - end_line = method.source.count("\n") + start_line - 1 - - return file, start_line..end_line - end - end - end - end -end |