diff options
author | David Heinemeier Hansson <david@loudthinking.com> | 2006-06-16 10:07:13 +0000 |
---|---|---|
committer | David Heinemeier Hansson <david@loudthinking.com> | 2006-06-16 10:07:13 +0000 |
commit | 36dc94a6a1e742848c5a80975b8bf5d216f54022 (patch) | |
tree | 4e22f73746eded676c8109c36683380418b893df /activesupport/lib/active_support/core_ext/hash/conversions.rb | |
parent | 7c326a3b54aaeb572a69dabb62fdc453d4814cf3 (diff) | |
download | rails-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.rb | 70 |
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(/</, "<"). + gsub(/>/, ">"). + gsub(/"/, '"'). + gsub(/'/, "'"). + gsub(/&/, "&") + 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 |