aboutsummaryrefslogtreecommitdiffstats
path: root/activesupport/lib/active_support/core_ext/hash/conversions.rb
diff options
context:
space:
mode:
authorDavid Heinemeier Hansson <david@loudthinking.com>2006-06-16 10:07:13 +0000
committerDavid Heinemeier Hansson <david@loudthinking.com>2006-06-16 10:07:13 +0000
commit36dc94a6a1e742848c5a80975b8bf5d216f54022 (patch)
tree4e22f73746eded676c8109c36683380418b893df /activesupport/lib/active_support/core_ext/hash/conversions.rb
parent7c326a3b54aaeb572a69dabb62fdc453d4814cf3 (diff)
downloadrails-36dc94a6a1e742848c5a80975b8bf5d216f54022.tar.gz
rails-36dc94a6a1e742848c5a80975b8bf5d216f54022.tar.bz2
rails-36dc94a6a1e742848c5a80975b8bf5d216f54022.zip
Added Hash.create_from_xml(string) which will create a hash from a XML string and even typecast if possible [DHH]
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@4453 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
Diffstat (limited to 'activesupport/lib/active_support/core_ext/hash/conversions.rb')
-rw-r--r--activesupport/lib/active_support/core_ext/hash/conversions.rb70
1 files changed, 70 insertions, 0 deletions
diff --git a/activesupport/lib/active_support/core_ext/hash/conversions.rb b/activesupport/lib/active_support/core_ext/hash/conversions.rb
index a3270c31ef..ac4a612e49 100644
--- a/activesupport/lib/active_support/core_ext/hash/conversions.rb
+++ b/activesupport/lib/active_support/core_ext/hash/conversions.rb
@@ -1,4 +1,5 @@
require 'date'
+require 'xml_simple'
module ActiveSupport #:nodoc:
module CoreExtensions #:nodoc:
@@ -20,6 +21,10 @@ module ActiveSupport #:nodoc:
"binary" => Proc.new { |binary| Base64.encode64(binary) }
}
+ def self.included(klass)
+ klass.extend(ClassMethods)
+ end
+
def to_xml(options = {})
options[:indent] ||= 2
options.reverse_merge!({ :builder => Builder::XmlMarkup.new(:indent => options[:indent]),
@@ -70,6 +75,71 @@ module ActiveSupport #:nodoc:
end
end
+
+ module ClassMethods
+ def create_from_xml(xml)
+ # TODO: Refactor this into something much cleaner that doesn't rely on XmlSimple
+ undasherize_keys(typecast_xml_value(XmlSimple.xml_in(xml,
+ 'forcearray' => false,
+ 'forcecontent' => true,
+ 'keeproot' => true,
+ 'contentkey' => '__content__')
+ ))
+ end
+
+ private
+ def typecast_xml_value(value)
+ case value.class.to_s
+ when "Hash"
+ if value.has_key?("__content__")
+ content = translate_xml_entities(value["__content__"])
+ case value["type"]
+ when "integer" then content.to_i
+ when "boolean" then content == "true"
+ when "datetime" then ::Time.parse(content).utc
+ when "date" then ::Date.parse(content)
+ else content
+ end
+ else
+ value.empty? ? nil : value.inject({}) do |h,(k,v)|
+ h[k] = typecast_xml_value(v)
+ h
+ end
+ end
+ when "Array"
+ value.map! { |i| typecast_xml_value(i) }
+ case value.length
+ when 0 then nil
+ when 1 then value.first
+ else value
+ end
+ else
+ raise "can't typecast #{value.inspect}"
+ end
+ end
+
+ def translate_xml_entities(value)
+ value.gsub(/&lt;/, "<").
+ gsub(/&gt;/, ">").
+ gsub(/&quot;/, '"').
+ gsub(/&apos;/, "'").
+ gsub(/&amp;/, "&")
+ end
+
+ def undasherize_keys(params)
+ case params.class.to_s
+ when "Hash"
+ params.inject({}) do |h,(k,v)|
+ h[k.to_s.tr("-", "_")] = undasherize_keys(v)
+ h
+ end
+ when "Array"
+ params.map { |v| undasherize_keys(v) }
+ else
+ params
+ end
+ end
+ end
end
end
end