diff options
Diffstat (limited to 'activesupport/lib/active_support/core_ext/hash/conversions.rb')
-rw-r--r-- | activesupport/lib/active_support/core_ext/hash/conversions.rb | 48 |
1 files changed, 27 insertions, 21 deletions
diff --git a/activesupport/lib/active_support/core_ext/hash/conversions.rb b/activesupport/lib/active_support/core_ext/hash/conversions.rb index 2763af6121..3005fef44c 100644 --- a/activesupport/lib/active_support/core_ext/hash/conversions.rb +++ b/activesupport/lib/active_support/core_ext/hash/conversions.rb @@ -7,7 +7,7 @@ require 'active_support/core_ext/string/inflections' class Hash # Returns a string containing an XML representation of its receiver: - # + # # {"foo" => 1, "bar" => 2}.to_xml # # => # # <?xml version="1.0" encoding="UTF-8"?> @@ -15,22 +15,34 @@ class Hash # # <foo type="integer">1</foo> # # <bar type="integer">2</bar> # # </hash> - # + # # To do so, the method loops over the pairs and builds nodes that depend on # the _values_. Given a pair +key+, +value+: - # + # # * If +value+ is a hash there's a recursive call with +key+ as <tt>:root</tt>. - # + # # * If +value+ is an array there's a recursive call with +key+ as <tt>:root</tt>, # and +key+ singularized as <tt>:children</tt>. - # + # # * If +value+ is a callable object it must expect one or two arguments. Depending # on the arity, the callable is invoked with the +options+ hash as first argument - # with +key+ as <tt>:root</tt>, and +key+ singularized as second argument. Its - # return value becomes a new node. - # + # with +key+ as <tt>:root</tt>, and +key+ singularized as second argument. The + # callable can add nodes by using <tt>options[:builder]</tt>. + # + # "foo".to_xml(lambda { |options, key| options[:builder].b(key) }) + # # => "<b>foo</b>" + # # * If +value+ responds to +to_xml+ the method is invoked with +key+ as <tt>:root</tt>. - # + # + # class Foo + # def to_xml(options) + # options[:builder].bar "fooing!" + # end + # end + # + # {:foo => Foo.new}.to_xml(:skip_instruct => true) + # # => "<hash><bar>fooing!</bar></hash>" + # # * Otherwise, a node with +key+ as tag is created with a string representation of # +value+ as text node. If +value+ is +nil+ an attribute "nil" set to "true" is added. # Unless the option <tt>:skip_types</tt> exists and is true, an attribute "type" is @@ -48,9 +60,9 @@ class Hash # "DateTime" => "datetime", # "Time" => "datetime" # } - # + # # By default the root node is "hash", but that's configurable via the <tt>:root</tt> option. - # + # # The default XML builder is a fresh instance of <tt>Builder::XmlMarkup</tt>. You can # configure your own builder with the <tt>:builder</tt> option. The method also accepts # options like <tt>:dasherize</tt> and friends, they are forwarded to the builder. @@ -108,17 +120,14 @@ class Hash # 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 + # 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 = value.inject({}) do |h,(k,v)| - h[k] = typecast_xml_value(v) - h - end - + xml_value = Hash[value.map { |k,v| [k, typecast_xml_value(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 @@ -136,10 +145,7 @@ class Hash def unrename_keys(params) case params.class.to_s when "Hash" - params.inject({}) do |h,(k,v)| - h[k.to_s.tr("-", "_")] = unrename_keys(v) - h - end + Hash[params.map { |k,v| [k.to_s.tr("-", "_"), unrename_keys(v)] } ] when "Array" params.map { |v| unrename_keys(v) } else |