aboutsummaryrefslogtreecommitdiffstats
path: root/activesupport/lib
diff options
context:
space:
mode:
Diffstat (limited to 'activesupport/lib')
-rw-r--r--activesupport/lib/active_support/callbacks.rb6
-rw-r--r--activesupport/lib/active_support/core_ext/array/access.rb6
-rw-r--r--activesupport/lib/active_support/core_ext/file/atomic.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/kernel/reporting.rb6
-rw-r--r--activesupport/lib/active_support/core_ext/object/try.rb45
-rw-r--r--activesupport/lib/active_support/core_ext/object/with_options.rb16
-rw-r--r--activesupport/lib/active_support/core_ext/string/output_safety.rb2
-rw-r--r--activesupport/lib/active_support/dependencies.rb10
-rw-r--r--activesupport/lib/active_support/hash_with_indifferent_access.rb1
-rw-r--r--activesupport/lib/active_support/inflector/inflections.rb2
-rw-r--r--activesupport/lib/active_support/inflector/methods.rb2
-rw-r--r--activesupport/lib/active_support/json/decoding.rb2
-rw-r--r--activesupport/lib/active_support/json/encoding.rb4
-rw-r--r--activesupport/lib/active_support/message_verifier.rb14
-rw-r--r--activesupport/lib/active_support/number_helper.rb10
-rw-r--r--activesupport/lib/active_support/number_helper/number_to_currency_converter.rb2
-rw-r--r--activesupport/lib/active_support/number_helper/number_to_percentage_converter.rb2
-rw-r--r--activesupport/lib/active_support/security_utils.rb20
-rw-r--r--activesupport/lib/active_support/test_case.rb2
-rw-r--r--activesupport/lib/active_support/testing/time_helpers.rb4
-rw-r--r--activesupport/lib/active_support/time_with_zone.rb16
21 files changed, 110 insertions, 64 deletions
diff --git a/activesupport/lib/active_support/callbacks.rb b/activesupport/lib/active_support/callbacks.rb
index 4bc13f20ca..24c702b602 100644
--- a/activesupport/lib/active_support/callbacks.rb
+++ b/activesupport/lib/active_support/callbacks.rb
@@ -78,7 +78,7 @@ module ActiveSupport
# save
# end
def run_callbacks(kind, &block)
- send "run_#{kind}_callbacks", &block
+ send "_run_#{kind}_callbacks", &block
end
private
@@ -559,7 +559,7 @@ module ActiveSupport
# This is used internally to append, prepend and skip callbacks to the
# CallbackChain.
def __update_callbacks(name) #:nodoc:
- ([self] + ActiveSupport::DescendantsTracker.descendants(self)).reverse.each do |target|
+ ([self] + ActiveSupport::DescendantsTracker.descendants(self)).reverse_each do |target|
chain = target.get_callbacks name
yield target, chain.dup
end
@@ -730,7 +730,7 @@ module ActiveSupport
set_callbacks name, CallbackChain.new(name, options)
module_eval <<-RUBY, __FILE__, __LINE__ + 1
- def run_#{name}_callbacks(&block)
+ def _run_#{name}_callbacks(&block)
_run_callbacks(_#{name}_callbacks, &block)
end
RUBY
diff --git a/activesupport/lib/active_support/core_ext/array/access.rb b/activesupport/lib/active_support/core_ext/array/access.rb
index caa499dfa2..45b89d2705 100644
--- a/activesupport/lib/active_support/core_ext/array/access.rb
+++ b/activesupport/lib/active_support/core_ext/array/access.rb
@@ -20,7 +20,11 @@ class Array
# %w( a b c d ).to(-2) # => ["a", "b", "c"]
# %w( a b c ).to(-10) # => []
def to(position)
- self[0..position]
+ if position >= 0
+ first position + 1
+ else
+ self[0..position]
+ end
end
# Equal to <tt>self[1]</tt>.
diff --git a/activesupport/lib/active_support/core_ext/file/atomic.rb b/activesupport/lib/active_support/core_ext/file/atomic.rb
index 0e7e3ba378..38374af388 100644
--- a/activesupport/lib/active_support/core_ext/file/atomic.rb
+++ b/activesupport/lib/active_support/core_ext/file/atomic.rb
@@ -40,7 +40,7 @@ class File
chown(old_stat.uid, old_stat.gid, file_name)
# This operation will affect filesystem ACL's
chmod(old_stat.mode, file_name)
- rescue Errno::EPERM
+ rescue Errno::EPERM, Errno::EACCES
# Changing file ownership failed, moving on.
end
end
diff --git a/activesupport/lib/active_support/core_ext/kernel/reporting.rb b/activesupport/lib/active_support/core_ext/kernel/reporting.rb
index 80c531b694..f5179552bb 100644
--- a/activesupport/lib/active_support/core_ext/kernel/reporting.rb
+++ b/activesupport/lib/active_support/core_ext/kernel/reporting.rb
@@ -32,7 +32,7 @@ module Kernel
# For compatibility
def silence_stderr #:nodoc:
ActiveSupport::Deprecation.warn(
- "#silence_stderr is deprecated and will be removed in the next release"
+ "`#silence_stderr` is deprecated and will be removed in the next release."
) #not thread-safe
silence_stream(STDERR) { yield }
end
@@ -87,7 +87,7 @@ module Kernel
# stream # => "error\n"
def capture(stream)
ActiveSupport::Deprecation.warn(
- "#capture(stream) is deprecated and will be removed in the next release"
+ "`#capture(stream)` is deprecated and will be removed in the next release."
) #not thread-safe
stream = stream.to_s
captured_stream = Tempfile.new(stream)
@@ -113,7 +113,7 @@ module Kernel
# This method is not thread-safe.
def quietly
ActiveSupport::Deprecation.warn(
- "#quietly is deprecated and will be removed in the next release"
+ "`#quietly` is deprecated and will be removed in the next release."
) #not thread-safe
silence_stream(STDOUT) do
silence_stream(STDERR) do
diff --git a/activesupport/lib/active_support/core_ext/object/try.rb b/activesupport/lib/active_support/core_ext/object/try.rb
index 31919474ed..56da398978 100644
--- a/activesupport/lib/active_support/core_ext/object/try.rb
+++ b/activesupport/lib/active_support/core_ext/object/try.rb
@@ -9,7 +9,23 @@ class Object
#
# instead of
#
- # @person ? @person.name : nil
+ # @person.name if @person
+ #
+ # +try+ calls can be chained:
+ #
+ # @person.try(:spouse).try(:name)
+ #
+ # instead of
+ #
+ # @person.spouse.name if @person && @person.spouse
+ #
+ # +try+ will also return +nil+ if the receiver does not respond to the method:
+ #
+ # @person.try(:non_existing_method) #=> nil
+ #
+ # instead of
+ #
+ # @person.non_existing_method if @person.respond_to?(:non_existing_method) #=> nil
#
# +try+ returns +nil+ when called on +nil+ regardless of whether it responds
# to the method:
@@ -24,7 +40,7 @@ class Object
#
# The number of arguments in the signature must match. If the object responds
# to the method the call is attempted and +ArgumentError+ is still raised
- # otherwise.
+ # in case of argument mismatch.
#
# If +try+ is called without arguments it yields the receiver to a given
# block unless it is +nil+:
@@ -38,12 +54,19 @@ class Object
#
# @person.try { upcase.truncate(50) }
#
- # Please also note that +try+ is defined on +Object+, therefore it won't work
+ # Please also note that +try+ is defined on +Object+. Therefore, it won't work
# with instances of classes that do not have +Object+ among their ancestors,
# like direct subclasses of +BasicObject+. For example, using +try+ with
# +SimpleDelegator+ will delegate +try+ to the target instead of calling it on
- # delegator itself.
+ # the delegator itself.
def try(*a, &b)
+ try!(*a, &b) if a.empty? || respond_to?(a.first)
+ end
+
+ # Same as #try, but will raise a NoMethodError exception if the receiver is not +nil+ and
+ # does not implement the tried method.
+
+ def try!(*a, &b)
if a.empty? && block_given?
if b.arity.zero?
instance_eval(&b)
@@ -51,16 +74,6 @@ class Object
yield self
end
else
- public_send(*a, &b) if respond_to?(a.first)
- end
- end
-
- # Same as #try, but will raise a NoMethodError exception if the receiving is not nil and
- # does not implement the tried method.
- def try!(*a, &b)
- if a.empty? && block_given?
- yield self
- else
public_send(*a, &b)
end
end
@@ -68,12 +81,12 @@ end
class NilClass
# Calling +try+ on +nil+ always returns +nil+.
- # It becomes specially helpful when navigating through associations that may return +nil+.
+ # It becomes especially helpful when navigating through associations that may return +nil+.
#
# nil.try(:name) # => nil
#
# Without +try+
- # @person && !@person.children.blank? && @person.children.first.name
+ # @person && @person.children.any? && @person.children.first.name
#
# With +try+
# @person.try(:children).try(:first).try(:name)
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 42e87c4424..7d38e1d134 100644
--- a/activesupport/lib/active_support/core_ext/object/with_options.rb
+++ b/activesupport/lib/active_support/core_ext/object/with_options.rb
@@ -47,7 +47,21 @@ class Object
# end
#
# <tt>with_options</tt> can also be nested since the call is forwarded to its receiver.
- # Each nesting level will merge inherited defaults in addition to their own.
+ #
+ # NOTE: Each nesting level will merge inherited defaults in addition to their own.
+ #
+ # class Post < ActiveRecord::Base
+ # with_options if: :persisted?, length: { minimum: 50 } do
+ # validates :content, if: -> { content.present? }
+ # end
+ # end
+ #
+ # The code is equivalent to:
+ #
+ # validates :content, length: { minimum: 50 }, if: -> { content.present? }
+ #
+ # Hence the inherited default for `if` key is ignored.
+ #
def with_options(options, &block)
option_merger = ActiveSupport::OptionMerger.new(self, options)
block.arity.zero? ? option_merger.instance_eval(&block) : block.call(option_merger)
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 c761325108..042283e4fc 100644
--- a/activesupport/lib/active_support/core_ext/string/output_safety.rb
+++ b/activesupport/lib/active_support/core_ext/string/output_safety.rb
@@ -150,7 +150,7 @@ module ActiveSupport #:nodoc:
else
if html_safe?
new_safe_buffer = super
- new_safe_buffer.instance_eval { @html_safe = true }
+ new_safe_buffer.instance_variable_set :@html_safe, true
new_safe_buffer
else
to_str[*args]
diff --git a/activesupport/lib/active_support/dependencies.rb b/activesupport/lib/active_support/dependencies.rb
index 93a11d4586..a89c769e34 100644
--- a/activesupport/lib/active_support/dependencies.rb
+++ b/activesupport/lib/active_support/dependencies.rb
@@ -30,6 +30,10 @@ module ActiveSupport #:nodoc:
mattr_accessor :loaded
self.loaded = Set.new
+ # Stack of files being loaded.
+ mattr_accessor :loading
+ self.loading = []
+
# Should we load files or require them?
mattr_accessor :mechanism
self.mechanism = ENV['NO_RELOAD'] ? :require : :load
@@ -317,6 +321,7 @@ module ActiveSupport #:nodoc:
def clear
log_call
loaded.clear
+ loading.clear
remove_unloadable_constants!
end
@@ -329,6 +334,7 @@ module ActiveSupport #:nodoc:
# Record that we've seen this file *before* loading it to avoid an
# infinite loop with mutual dependencies.
loaded << expanded
+ loading << expanded
begin
if load?
@@ -351,6 +357,8 @@ module ActiveSupport #:nodoc:
rescue Exception
loaded.delete expanded
raise
+ ensure
+ loading.pop
end
# Record history *after* loading so first load gets warnings.
@@ -475,7 +483,7 @@ module ActiveSupport #:nodoc:
expanded = File.expand_path(file_path)
expanded.sub!(/\.rb\z/, '')
- if loaded.include?(expanded)
+ if loading.include?(expanded)
raise "Circular dependency detected while autoloading constant #{qualified_name}"
else
require_or_load(expanded, qualified_name)
diff --git a/activesupport/lib/active_support/hash_with_indifferent_access.rb b/activesupport/lib/active_support/hash_with_indifferent_access.rb
index 3d8f2d572b..1468c62151 100644
--- a/activesupport/lib/active_support/hash_with_indifferent_access.rb
+++ b/activesupport/lib/active_support/hash_with_indifferent_access.rb
@@ -1,4 +1,5 @@
require 'active_support/core_ext/hash/keys'
+require 'active_support/core_ext/hash/reverse_merge'
module ActiveSupport
# Implements a hash where keys <tt>:foo</tt> and <tt>"foo"</tt> are considered
diff --git a/activesupport/lib/active_support/inflector/inflections.rb b/activesupport/lib/active_support/inflector/inflections.rb
index 97401ccec7..486838bd15 100644
--- a/activesupport/lib/active_support/inflector/inflections.rb
+++ b/activesupport/lib/active_support/inflector/inflections.rb
@@ -154,7 +154,7 @@ module ActiveSupport
end
end
- # Add uncountable words that shouldn't be attempted inflected.
+ # Specifies words that are uncountable and should not be inflected.
#
# uncountable 'money'
# uncountable 'money', 'information'
diff --git a/activesupport/lib/active_support/inflector/methods.rb b/activesupport/lib/active_support/inflector/methods.rb
index 0e3c8517d1..637736c5df 100644
--- a/activesupport/lib/active_support/inflector/methods.rb
+++ b/activesupport/lib/active_support/inflector/methods.rb
@@ -90,7 +90,7 @@ module ActiveSupport
# 'SSLError'.underscore.camelize # => "SslError"
def underscore(camel_cased_word)
return camel_cased_word unless camel_cased_word =~ /[A-Z-]|::/
- word = camel_cased_word.to_s.gsub('::', '/')
+ word = camel_cased_word.to_s.gsub(/::/, '/')
word.gsub!(/(?:(?<=([A-Za-z\d]))|\b)(#{inflections.acronym_regex})(?=\b|[^a-z])/) { "#{$1 && '_'}#{$2.downcase}" }
word.gsub!(/([A-Z\d]+)([A-Z][a-z])/,'\1_\2')
word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
diff --git a/activesupport/lib/active_support/json/decoding.rb b/activesupport/lib/active_support/json/decoding.rb
index 8b5fc70dee..35548f3f56 100644
--- a/activesupport/lib/active_support/json/decoding.rb
+++ b/activesupport/lib/active_support/json/decoding.rb
@@ -12,7 +12,7 @@ module ActiveSupport
class << self
# Parses a JSON string (JavaScript Object Notation) into a hash.
- # See www.json.org for more info.
+ # See http://www.json.org for more info.
#
# ActiveSupport::JSON.decode("{\"team\":\"rails\",\"players\":\"36\"}")
# => {"team" => "rails", "players" => "36"}
diff --git a/activesupport/lib/active_support/json/encoding.rb b/activesupport/lib/active_support/json/encoding.rb
index f29d42276d..c0ac5af153 100644
--- a/activesupport/lib/active_support/json/encoding.rb
+++ b/activesupport/lib/active_support/json/encoding.rb
@@ -13,7 +13,7 @@ module ActiveSupport
module JSON
# Dumps objects in JSON (JavaScript Object Notation).
- # See www.json.org for more info.
+ # See http://www.json.org for more info.
#
# ActiveSupport::JSON.encode({ team: 'rails', players: '36' })
# # => "{\"team\":\"rails\",\"players\":\"36\"}"
@@ -131,7 +131,7 @@ module ActiveSupport
"The JSON encoder in Rails 4.1 no longer supports encoding BigDecimals as JSON numbers. Instead, " \
"the new encoder will always encode them as strings.\n\n" \
"You are seeing this error because you are trying to check the value of the related configuration, " \
- "'active_support.encode_big_decimal_as_string'. If your application depends on this option, you should " \
+ "`active_support.encode_big_decimal_as_string`. If your application depends on this option, you should " \
"add the 'activesupport-json_encoder' gem to your Gemfile. For now, this option will always be true. " \
"In the future, it will be removed from Rails, so you should stop checking its value."
diff --git a/activesupport/lib/active_support/message_verifier.rb b/activesupport/lib/active_support/message_verifier.rb
index 6cb2884fb7..4e0796f4f8 100644
--- a/activesupport/lib/active_support/message_verifier.rb
+++ b/activesupport/lib/active_support/message_verifier.rb
@@ -1,5 +1,6 @@
require 'base64'
require 'active_support/core_ext/object/blank'
+require 'active_support/security_utils'
module ActiveSupport
# +MessageVerifier+ makes it easy to generate and verify messages which are
@@ -37,7 +38,7 @@ module ActiveSupport
raise InvalidSignature if signed_message.blank?
data, digest = signed_message.split("--")
- if data.present? && digest.present? && secure_compare(digest, generate_digest(data))
+ if data.present? && digest.present? && ActiveSupport::SecurityUtils.secure_compare(digest, generate_digest(data))
begin
@serializer.load(::Base64.strict_decode64(data))
rescue ArgumentError => argument_error
@@ -55,17 +56,6 @@ module ActiveSupport
end
private
- # constant-time comparison algorithm to prevent timing attacks
- def secure_compare(a, b)
- return false unless a.bytesize == b.bytesize
-
- l = a.unpack "C#{a.bytesize}"
-
- res = 0
- b.each_byte { |byte| res |= byte ^ l.shift }
- res == 0
- end
-
def generate_digest(data)
require 'openssl' unless defined?(OpenSSL)
OpenSSL::HMAC.hexdigest(OpenSSL::Digest.const_get(@digest).new, @secret, data)
diff --git a/activesupport/lib/active_support/number_helper.rb b/activesupport/lib/active_support/number_helper.rb
index 5ecda9593a..34439ee8be 100644
--- a/activesupport/lib/active_support/number_helper.rb
+++ b/activesupport/lib/active_support/number_helper.rb
@@ -272,12 +272,12 @@ module ActiveSupport
# string containing an i18n scope where to find this hash. It
# might have the following keys:
# * *integers*: <tt>:unit</tt>, <tt>:ten</tt>,
- # *<tt>:hundred</tt>, <tt>:thousand</tt>, <tt>:million</tt>,
- # *<tt>:billion</tt>, <tt>:trillion</tt>,
- # *<tt>:quadrillion</tt>
+ # <tt>:hundred</tt>, <tt>:thousand</tt>, <tt>:million</tt>,
+ # <tt>:billion</tt>, <tt>:trillion</tt>,
+ # <tt>:quadrillion</tt>
# * *fractionals*: <tt>:deci</tt>, <tt>:centi</tt>,
- # *<tt>:mili</tt>, <tt>:micro</tt>, <tt>:nano</tt>,
- # *<tt>:pico</tt>, <tt>:femto</tt>
+ # <tt>:mili</tt>, <tt>:micro</tt>, <tt>:nano</tt>,
+ # <tt>:pico</tt>, <tt>:femto</tt>
# * <tt>:format</tt> - Sets the format of the output string
# (defaults to "%n %u"). The field types are:
# * %u - The quantifier (ex.: 'thousand')
diff --git a/activesupport/lib/active_support/number_helper/number_to_currency_converter.rb b/activesupport/lib/active_support/number_helper/number_to_currency_converter.rb
index 9ae27a896a..fb5adb574a 100644
--- a/activesupport/lib/active_support/number_helper/number_to_currency_converter.rb
+++ b/activesupport/lib/active_support/number_helper/number_to_currency_converter.rb
@@ -13,7 +13,7 @@ module ActiveSupport
end
rounded_number = NumberToRoundedConverter.convert(number, options)
- format.gsub('%n', rounded_number).gsub('%u', options[:unit])
+ format.gsub(/%n/, rounded_number).gsub(/%u/, options[:unit])
end
private
diff --git a/activesupport/lib/active_support/number_helper/number_to_percentage_converter.rb b/activesupport/lib/active_support/number_helper/number_to_percentage_converter.rb
index eafe2844f7..1af294a03e 100644
--- a/activesupport/lib/active_support/number_helper/number_to_percentage_converter.rb
+++ b/activesupport/lib/active_support/number_helper/number_to_percentage_converter.rb
@@ -5,7 +5,7 @@ module ActiveSupport
def convert
rounded_number = NumberToRoundedConverter.convert(number, options)
- options[:format].gsub('%n', rounded_number)
+ options[:format].gsub(/%n/, rounded_number)
end
end
end
diff --git a/activesupport/lib/active_support/security_utils.rb b/activesupport/lib/active_support/security_utils.rb
new file mode 100644
index 0000000000..64c4801179
--- /dev/null
+++ b/activesupport/lib/active_support/security_utils.rb
@@ -0,0 +1,20 @@
+module ActiveSupport
+ module SecurityUtils
+ # Constant time string comparison.
+ #
+ # The values compared should be of fixed length, such as strings
+ # that have already been processed by HMAC. This should not be used
+ # on variable length plaintext strings because it could leak length info
+ # via timing attacks.
+ def secure_compare(a, b)
+ return false unless a.bytesize == b.bytesize
+
+ l = a.unpack "C#{a.bytesize}"
+
+ res = 0
+ b.each_byte { |byte| res |= byte ^ l.shift }
+ res == 0
+ end
+ module_function :secure_compare
+ end
+end
diff --git a/activesupport/lib/active_support/test_case.rb b/activesupport/lib/active_support/test_case.rb
index 4c3e77b7fd..a4ba5989b1 100644
--- a/activesupport/lib/active_support/test_case.rb
+++ b/activesupport/lib/active_support/test_case.rb
@@ -25,7 +25,7 @@ module ActiveSupport
if test_order.nil?
ActiveSupport::Deprecation.warn "You did not specify a value for the " \
- "configuration option 'active_support.test_order'. In Rails 5.0, " \
+ "configuration option `active_support.test_order`. In Rails 5, " \
"the default value of this option will change from `:sorted` to " \
"`:random`.\n" \
"To disable this warning and keep the current behavior, you can add " \
diff --git a/activesupport/lib/active_support/testing/time_helpers.rb b/activesupport/lib/active_support/testing/time_helpers.rb
index 1112c6e0b1..8c63815660 100644
--- a/activesupport/lib/active_support/testing/time_helpers.rb
+++ b/activesupport/lib/active_support/testing/time_helpers.rb
@@ -90,7 +90,7 @@ module ActiveSupport
# Time.current # => Wed, 24 Nov 2004 01:04:44 EST -05:00
# end
# Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
- def travel_to(date_or_time, &block)
+ def travel_to(date_or_time)
if date_or_time.is_a?(Date) && !date_or_time.is_a?(DateTime)
now = date_or_time.midnight.to_time
else
@@ -102,7 +102,7 @@ module ActiveSupport
if block_given?
begin
- block.call
+ yield
ensure
travel_back
end
diff --git a/activesupport/lib/active_support/time_with_zone.rb b/activesupport/lib/active_support/time_with_zone.rb
index 4a0ed356b1..dbee145196 100644
--- a/activesupport/lib/active_support/time_with_zone.rb
+++ b/activesupport/lib/active_support/time_with_zone.rb
@@ -75,8 +75,8 @@ module ActiveSupport
# Returns a <tt>Time.local()</tt> instance of the simultaneous time in your
# system's <tt>ENV['TZ']</tt> zone.
- def localtime
- utc.respond_to?(:getlocal) ? utc.getlocal : utc.to_time.getlocal
+ def localtime(utc_offset = nil)
+ utc.respond_to?(:getlocal) ? utc.getlocal(utc_offset) : utc.to_time.getlocal(utc_offset)
end
alias_method :getlocal, :localtime
@@ -201,15 +201,11 @@ module ActiveSupport
end
alias_method :to_formatted_s, :to_s
- # Replaces <tt>%Z</tt> and <tt>%z</tt> directives with +zone+ and
- # +formatted_offset+, respectively, before passing to Time#strftime, so
- # that zone information is correct
+ # Replaces <tt>%Z</tt> directive with +zone before passing to Time#strftime,
+ # so that zone information is correct.
def strftime(format)
- format = format.gsub('%Z', zone)
- .gsub('%z', formatted_offset(false))
- .gsub('%:z', formatted_offset(true))
- .gsub('%::z', formatted_offset(true) + ":00")
- time.strftime(format)
+ format = format.gsub(/((?:\A|[^%])(?:%%)*)%Z/, "\\1#{zone}")
+ getlocal(utc_offset).strftime(format)
end
# Use the time in UTC for comparisons.