aboutsummaryrefslogtreecommitdiffstats
path: root/activesupport
diff options
context:
space:
mode:
authorDavid Heinemeier Hansson <david@loudthinking.com>2007-04-25 17:25:44 +0000
committerDavid Heinemeier Hansson <david@loudthinking.com>2007-04-25 17:25:44 +0000
commit6a85955642606aa3159ea8e4d24fbc77a1fc5e94 (patch)
tree616c37e17c1b14fbece4a319fc41ee63dba78072 /activesupport
parent54bc5ca8d97b7ef8640686e50168ba25d7f23d27 (diff)
downloadrails-6a85955642606aa3159ea8e4d24fbc77a1fc5e94.tar.gz
rails-6a85955642606aa3159ea8e4d24fbc77a1fc5e94.tar.bz2
rails-6a85955642606aa3159ea8e4d24fbc77a1fc5e94.zip
Added parsing of file type in Hash.xml_in so you can easily do file uploads with base64 from an API [DHH]
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@6578 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
Diffstat (limited to 'activesupport')
-rw-r--r--activesupport/CHANGELOG16
-rw-r--r--activesupport/lib/active_support/core_ext/hash/conversions.rb43
2 files changed, 47 insertions, 12 deletions
diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG
index ea734dcddf..018d6e977c 100644
--- a/activesupport/CHANGELOG
+++ b/activesupport/CHANGELOG
@@ -1,5 +1,21 @@
*SVN*
+* Added parsing of file type in Hash.xml_in so you can easily do file uploads with base64 from an API [DHH]
+
+ <person>
+ <name>David</name>
+ <avatar type="file" name="me.jpg" content_type="image/jpg">R0lGODlhkACZAPUAAM5lcfjrtMQCG=\n</avatar>
+ </person>
+
+ ...becomes:
+
+ attributes = { :person => { :name => "David", :avatar => #<StringIO> } }
+ attributes[:person][:avatar].content_type # => "image/jpg"
+ attributes[:person][:avatar].original_filename # => "me.jpg"
+ attributes[:person][:avatar].read # => binary data of the file
+
+ Which is duck-type compatible with the files that you get when doing multipart uploads through HTML.
+
* Improved multibyte performance by relying less on exception raising #8159 [Blaine]
* Use XSD-compatible type names for Hash#to_xml and make the converters extendable #8047 [Tim Pope]
diff --git a/activesupport/lib/active_support/core_ext/hash/conversions.rb b/activesupport/lib/active_support/core_ext/hash/conversions.rb
index 4fb3cbe4d3..a8f2ec4452 100644
--- a/activesupport/lib/active_support/core_ext/hash/conversions.rb
+++ b/activesupport/lib/active_support/core_ext/hash/conversions.rb
@@ -45,15 +45,22 @@ module ActiveSupport #:nodoc:
unless defined?(XML_PARSING)
XML_PARSING = {
- "date" => Proc.new { |date| ::Date.parse(date) },
- "datetime" => Proc.new { |time| ::Time.parse(time).utc },
- "integer" => Proc.new { |integer| integer.to_i },
- "float" => Proc.new { |float| float.to_f },
- "decimal" => Proc.new { |number| BigDecimal(number) },
- "boolean" => Proc.new { |boolean| %w(1 true).include?(boolean.strip) },
- "string" => Proc.new { |string| string.to_s },
- "yaml" => Proc.new { |yaml| YAML::load(yaml) rescue yaml },
- "base64Binary" => Proc.new { |bin| Base64.decode64(bin) }
+ "date" => Proc.new { |date| ::Date.parse(date) },
+ "datetime" => Proc.new { |time| ::Time.parse(time).utc },
+ "integer" => Proc.new { |integer| integer.to_i },
+ "float" => Proc.new { |float| float.to_f },
+ "decimal" => Proc.new { |number| BigDecimal(number) },
+ "boolean" => Proc.new { |boolean| %w(1 true).include?(boolean.strip) },
+ "string" => Proc.new { |string| string.to_s },
+ "yaml" => Proc.new { |yaml| YAML::load(yaml) rescue yaml },
+ "base64Binary" => Proc.new { |bin| Base64.decode64(bin) },
+ # FIXME: Get rid of eval and institute a proper decorator here
+ "file" => Proc.new do |file, entity|
+ f = StringIO.new(Base64.decode64(file))
+ eval "def f.original_filename() '#{entity["name"]}' || 'untitled' end"
+ eval "def f.content_type() '#{entity["content_type"]}' || 'application/octet-stream' end"
+ f
+ end
}
XML_PARSING.update(
@@ -147,18 +154,30 @@ module ActiveSupport #:nodoc:
when "Hash"
if value.has_key?("__content__")
content = translate_xml_entities(value["__content__"])
- if XML_PARSING[value["type"]]
- XML_PARSING[value["type"]].call(content)
+ if parser = XML_PARSING[value["type"]]
+ if parser.arity == 2
+ XML_PARSING[value["type"]].call(content, value)
+ else
+ XML_PARSING[value["type"]].call(content)
+ end
else
content
end
elsif value['type'] == 'string' && value['nil'] != 'true'
""
else
- (value.blank? || value['type'] || value['nil'] == 'true') ? nil : value.inject({}) do |h,(k,v)|
+ xml_value = (value.blank? || value['type'] || value['nil'] == 'true') ? nil : value.inject({}) do |h,(k,v)|
h[k] = typecast_xml_value(v)
h
end
+
+ # Turn { :files => { :file => #<StringIO> } into { :files => #<StringIO> } so it is compatible with
+ # how multipart uploaded files from HTML appear
+ if xml_value["file"].is_a?(StringIO)
+ xml_value["file"]
+ else
+ xml_value
+ end
end
when "Array"
value.map! { |i| typecast_xml_value(i) }