Search code examples
ruby-on-railsxml-serializationruby-on-rails-2ruby-1.8.7

Rails 2: #to_xml(:methods => :method_name) when #method_name returns an Array


Is it possible to override how #to_xml renders a method result if it's an Array?

Given #numbers is not a field but a method And @object.numbers #=> [0,1,2,3,4,5]

currently it does:

@object.to_xml(:methods => :numbers)
=> "<object><numbers>012345</numbers></object>"

is it possible to override this behavior so it returns:

@object.to_xml(:methods => :numbers)
=> "<object>
      <numbers>
        <number>0</number>
        <number>1</number>
        <number>2</number>
        <number>3</number>
        <number>4</number>
        <number>5</number>
      </numbers>
    </object>"

(formatted so it's easily read)

Thanks in advance for your suggestions!


Solution

  • You have two options:

    1. Upgrade to Rails 3. It already has the desired output.

      gem "activemodel", '~> 3.2.12'
      require "active_model"
      
      # This could be an Active Record model
      class Result
        include ActiveModel::Serializers::Xml
      
        def numbers
          (0..5).to_a
        end
      
        def attributes
          {}
        end
      end
      
      result = Result.new
      puts result.to_xml(:methods => :numbers)
      

      Outputs:

      <?xml version="1.0" encoding="UTF-8"?>
      <result>
        <numbers type="array">
          <number type="integer">0</number>
          <number type="integer">1</number>
          <number type="integer">2</number>
          <number type="integer">3</number>
          <number type="integer">4</number>
          <number type="integer">5</number>
        </numbers>
      </result>
      
    2. Use XML Builder where you are in full control of the output. You will have to specify all attributes manually.

      # app/views/results/show.xml.builder
      xml.instruct!
      xml.result {
        xml.numbers {
          result.numbers.each do |n|
            xml.number n
          end
        }
      }
      

      Outputs:

      <?xml version="1.0" encoding="UTF-8"?>
      <result>
        <numbers>
          <number>0</number>
          <number>1</number>
          <number>2</number>
          <number>3</number>
          <number>4</number>
          <number>5</number>
        </numbers>
      </result>