开发者

to_xml on Hash with string array fails with Not all elements respond to to_xml

to_xml on Hash with str开发者_运维问答ing array fails with Not all elements respond to to_xml

 >>r={"records"=>["001","002"]}

 => {"records"=>["001", "002"]}

 >>r.to_xml

 RuntimeError: Not all elements respond
 to to_xml   from
/jruby/../1.8/gems/activesupport2.3.9/lib/active_support/core_ext/array/conversions.rb:163:in `to_xml'

Is there a rails preferred way to change the Hash.to_xml behavior to return

<records>
 <record>001</record>
 <record>002</record>
</records>

...


Just like DigitalRoss said, this appears to work out of the box in Ruby 1.9 with ActiveSupport 3:

ruby-1.9.2-p0 > require 'active_support/all'
 => true 
ruby-1.9.2-p0 > r={"records"=>["001","002"]}
 => {"records"=>["001", "002"]} 
ruby-1.9.2-p0 > puts r.to_xml
<?xml version="1.0" encoding="UTF-8"?>
<hash>
  <records type="array">
    <record>001</record>
    <record>002</record>
  </records>
</hash>

At least with MRI (you're using JRuby, though), you can get similar behavior on Ruby 1.8 with ActiveSupport 2.3.9:

require 'rubygems'
gem 'activesupport', '~>2.3'
require 'active_support'
class String
  def to_xml(options = {})
    root = options[:root] || 'string'
    options[:builder].tag! root, self
  end
end

Which gives you...

ruby-1.8.7-head > load 'myexample.rb'
 => true 
ruby-1.8.7-head > r={"records"=>["001","002"]}
 => {"records"=>["001", "002"]} 
ruby-1.8.7-head > puts r.to_xml
<?xml version="1.0" encoding="UTF-8"?>
<hash>
  <records type="array">
    <record>001</record>
    <record>002</record>
  </records>
</hash>

Note that my code doesn't work with Ruby 1.9 and ActiveRecord 3.


No, because there is no way that "001" and "002" know how to become <record>001</record>. These strings are just that: strings. They don't know that they are used in a hash with an array, let alone that these strings share a key, that needs to be singularized.

You could do something like:

record = Struct.new(:value) do
  def to_xml
    "<record>#{value}</record>"
  end
end

r = { "records" => [ record.new("001"), record.new("002") ] }
r.to_xml

Or, use a tool like Builder to make the xml separately from the data structure.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜