aboutsummaryrefslogtreecommitdiffstats
path: root/activesupport/lib/active_support/core_ext
diff options
context:
space:
mode:
Diffstat (limited to 'activesupport/lib/active_support/core_ext')
-rw-r--r--activesupport/lib/active_support/core_ext/array/wrap.rb3
-rw-r--r--activesupport/lib/active_support/core_ext/class/attribute.rb3
-rw-r--r--activesupport/lib/active_support/core_ext/hash/conversions.rb150
-rw-r--r--activesupport/lib/active_support/core_ext/logger.rb23
-rw-r--r--activesupport/lib/active_support/core_ext/string/inflections.rb4
-rw-r--r--activesupport/lib/active_support/core_ext/thread.rb6
6 files changed, 113 insertions, 76 deletions
diff --git a/activesupport/lib/active_support/core_ext/array/wrap.rb b/activesupport/lib/active_support/core_ext/array/wrap.rb
index 05b09a4c7f..1245768870 100644
--- a/activesupport/lib/active_support/core_ext/array/wrap.rb
+++ b/activesupport/lib/active_support/core_ext/array/wrap.rb
@@ -29,8 +29,7 @@ class Array
#
# [*object]
#
- # which for +nil+ returns <tt>[nil]</tt> (Ruby 1.8.7) or <tt>[]</tt> (Ruby
- # 1.9), and calls to <tt>Array(object)</tt> otherwise.
+ # which for +nil+ returns <tt>[]</tt>, and calls to <tt>Array(object)</tt> otherwise.
#
# Thus, in this case the behavior may be different for +nil+, and the differences with
# <tt>Kernel#Array</tt> explained above apply to the rest of <tt>object</tt>s.
diff --git a/activesupport/lib/active_support/core_ext/class/attribute.rb b/activesupport/lib/active_support/core_ext/class/attribute.rb
index 1504e18839..5d8d09aa69 100644
--- a/activesupport/lib/active_support/core_ext/class/attribute.rb
+++ b/activesupport/lib/active_support/core_ext/class/attribute.rb
@@ -69,7 +69,8 @@ class Class
# To opt out of both instance methods, pass <tt>instance_accessor: false</tt>.
def class_attribute(*attrs)
options = attrs.extract_options!
- instance_reader = options.fetch(:instance_accessor, true) && options.fetch(:instance_reader, true)
+ # double assignment is used to avoid "assigned but unused variable" warning
+ instance_reader = instance_reader = options.fetch(:instance_accessor, true) && options.fetch(:instance_reader, true)
instance_writer = options.fetch(:instance_accessor, true) && options.fetch(:instance_writer, true)
# We use class_eval here rather than define_method because class_attribute
diff --git a/activesupport/lib/active_support/core_ext/hash/conversions.rb b/activesupport/lib/active_support/core_ext/hash/conversions.rb
index e1ce9f371a..6cb7434e5f 100644
--- a/activesupport/lib/active_support/core_ext/hash/conversions.rb
+++ b/activesupport/lib/active_support/core_ext/hash/conversions.rb
@@ -102,55 +102,41 @@ class Hash
# hash = Hash.from_xml(xml)
# # => {"hash"=>{"foo"=>1, "bar"=>2}}
def from_xml(xml)
- typecast_xml_value(unrename_keys(ActiveSupport::XmlMini.parse(xml)))
+ ActiveSupport::XMLConverter.new(xml).to_h
+ end
+
+ end
+end
+
+module ActiveSupport
+ class XMLConverter # :nodoc:
+ def initialize(xml)
+ @xml = normalize_keys(XmlMini.parse(xml))
+ end
+
+ def to_h
+ deep_to_h(@xml)
end
private
- def typecast_xml_value(value)
- case value
+
+ def normalize_keys(params)
+ case params
when Hash
- if value['type'] == 'array'
- _, entries = Array.wrap(value.detect { |k,v| not v.is_a?(String) })
- if entries.nil? || (c = value['__content__'] && c.blank?)
- []
- else
- case entries # something weird with classes not matching here. maybe singleton methods breaking is_a?
- when Array
- entries.collect { |v| typecast_xml_value(v) }
- when Hash
- [typecast_xml_value(entries)]
- else
- raise "can't typecast #{entries.inspect}"
- end
- end
- elsif value['type'] == 'file' ||
- (value['__content__'] && (value.keys.size == 1 || value['__content__'].present?))
- content = value['__content__']
- if parser = ActiveSupport::XmlMini::PARSING[value['type']]
- parser.arity == 1 ? parser.call(content) : parser.call(content, value)
- else
- content
- end
- elsif value['type'] == 'string' && value['nil'] != 'true'
- ''
- # blank or nil parsed values are represented by nil
- elsif value.blank? || value['nil'] == 'true'
- nil
- # If the type is the only element which makes it then
- # this still makes the value nil, except if type is
- # a XML node(where type['value'] is a Hash)
- elsif value['type'] && value.size == 1 && !value['type'].is_a?(::Hash)
- nil
- else
- xml_value = Hash[value.map { |k,v| [k, typecast_xml_value(v)] }]
+ Hash[params.map { |k,v| [k.to_s.tr('-', '_'), normalize_keys(v)] } ]
+ when Array
+ params.map { |v| normalize_keys(v) }
+ else
+ params
+ end
+ end
- # Turn { files: { file: #<StringIO> } } into { files: #<StringIO> } so it is compatible with
- # how multipart uploaded files from HTML appear
- xml_value['file'].is_a?(StringIO) ? xml_value['file'] : xml_value
- end
+ def deep_to_h(value)
+ case value
+ when Hash
+ process_hash(value)
when Array
- value.map! { |i| typecast_xml_value(i) }
- value.length > 1 ? value : value.first
+ process_array(value)
when String
value
else
@@ -158,15 +144,79 @@ class Hash
end
end
- def unrename_keys(params)
- case params
- when Hash
- Hash[params.map { |k,v| [k.to_s.tr('-', '_'), unrename_keys(v)] } ]
- when Array
- params.map { |v| unrename_keys(v) }
+ def process_hash(value)
+ if become_array?(value)
+ _, entries = Array.wrap(value.detect { |k,v| not v.is_a?(String) })
+ if entries.nil? || value['__content__'].try(:empty?)
+ []
else
- params
+ case entries
+ when Array
+ entries.collect { |v| deep_to_h(v) }
+ when Hash
+ [deep_to_h(entries)]
+ else
+ raise "can't typecast #{entries.inspect}"
+ end
+ end
+ elsif become_content?(value)
+ process_content(value)
+
+ elsif become_empty_string?(value)
+ ''
+ elsif become_hash?(value)
+ xml_value = Hash[value.map { |k,v| [k, deep_to_h(v)] }]
+
+ # Turn { files: { file: #<StringIO> } } into { files: #<StringIO> } so it is compatible with
+ # how multipart uploaded files from HTML appear
+ xml_value['file'].is_a?(StringIO) ? xml_value['file'] : xml_value
end
end
+
+ def become_content?(value)
+ value['type'] == 'file' || (value['__content__'] && (value.keys.size == 1 || value['__content__'].present?))
+ end
+
+ def become_array?(value)
+ value['type'] == 'array'
+ end
+
+ def become_empty_string?(value)
+ # {"string" => true}
+ # No tests fail when the second term is removed.
+ value['type'] == 'string' && value['nil'] != 'true'
+ end
+
+ def become_hash?(value)
+ !nothing?(value) && !garbage?(value)
+ end
+
+ def nothing?(value)
+ # blank or nil parsed values are represented by nil
+ value.blank? || value['nil'] == 'true'
+ end
+
+ def garbage?(value)
+ # If the type is the only element which makes it then
+ # this still makes the value nil, except if type is
+ # a XML node(where type['value'] is a Hash)
+ value['type'] && !value['type'].is_a?(::Hash) && value.size == 1
+ end
+
+ def process_content(value)
+ content = value['__content__']
+ if parser = ActiveSupport::XmlMini::PARSING[value['type']]
+ parser.arity == 1 ? parser.call(content) : parser.call(content, value)
+ else
+ content
+ end
+ end
+
+ def process_array(value)
+ value.map! { |i| deep_to_h(i) }
+ value.length > 1 ? value : value.first
+ end
+
end
end
+
diff --git a/activesupport/lib/active_support/core_ext/logger.rb b/activesupport/lib/active_support/core_ext/logger.rb
index 16fce81445..34de766331 100644
--- a/activesupport/lib/active_support/core_ext/logger.rb
+++ b/activesupport/lib/active_support/core_ext/logger.rb
@@ -1,5 +1,6 @@
require 'active_support/core_ext/class/attribute_accessors'
require 'active_support/deprecation'
+require 'active_support/logger_silence'
ActiveSupport::Deprecation.warn 'this file is deprecated and will be removed'
@@ -31,27 +32,9 @@ require 'logger'
#
# logger.datetime_format = "%Y-%m-%d"
#
-# Note: This logger is deprecated in favor of ActiveSupport::BufferedLogger
+# Note: This logger is deprecated in favor of ActiveSupport::Logger
class Logger
- ##
- # :singleton-method:
- # Set to false to disable the silencer
- cattr_accessor :silencer
- self.silencer = true
-
- # 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
- yield self
- ensure
- self.level = old_logger_level
- end
- else
- yield self
- end
- end
+ include LoggerSilence
alias :old_datetime_format= :datetime_format=
# Logging date-time format (string passed to +strftime+). Ignored if the formatter
diff --git a/activesupport/lib/active_support/core_ext/string/inflections.rb b/activesupport/lib/active_support/core_ext/string/inflections.rb
index 341e2deec9..6522145572 100644
--- a/activesupport/lib/active_support/core_ext/string/inflections.rb
+++ b/activesupport/lib/active_support/core_ext/string/inflections.rb
@@ -193,8 +193,8 @@ class String
# Capitalizes the first word, turns underscores into spaces, and strips '_id'.
# Like +titleize+, this is meant for creating pretty output.
#
- # 'employee_salary' # => "Employee salary"
- # 'author_id' # => "Author"
+ # 'employee_salary'.humanize # => "Employee salary"
+ # 'author_id'.humanize # => "Author"
def humanize
ActiveSupport::Inflector.humanize(self)
end
diff --git a/activesupport/lib/active_support/core_ext/thread.rb b/activesupport/lib/active_support/core_ext/thread.rb
index 6ad0b2d69c..5481766f10 100644
--- a/activesupport/lib/active_support/core_ext/thread.rb
+++ b/activesupport/lib/active_support/core_ext/thread.rb
@@ -65,6 +65,10 @@ class Thread
private
def locals
- @locals || LOCK.synchronize { @locals ||= {} }
+ if defined?(@locals)
+ @locals
+ else
+ LOCK.synchronize { @locals ||= {} }
+ end
end
end unless Thread.instance_methods.include?(:thread_variable_set)