Making WillPaginate and Rails to_xml play nice with ActiveResource

We are currently working on a project that involves Flex and active resource + will_paginate and we needed to be able to paginate the xml transactions easily. Unfortunately, will_paginate and to_xml don't play nicely when it comes to adding the current_page, total_pages, and page attributes to the xml. After many failed attempts I went looking around github and found in a few forks of will paginate that some people had solved this problem but, I didn't want to install another version of the gem to risk breaking other apps on the server so I did it the rails way!

I started by creating a module that opens up the will_paginate collection class and includes ActiveResource and alias method chain the to_xml method to include these values. Example code below.

require 'to_xml_extensions'  
module WillPaginateHelpers  
  include ActiveSupport::CoreExtensions::Array::Conversions
  def to_xml_with_collection_type(options = {})
        serializeable_collection.to_xml_without_collection_type(options) do |xml|
          xml.tag!(:current_page, {:type => ActiveSupport::CoreExtensions::Hash::Conversions::XML_TYPE_NAMES[]}, current_page)
          xml.tag!(:per_page, {:type => ActiveSupport::CoreExtensions::Hash::Conversions::XML_TYPE_NAMES[]}, per_page)
          xml.tag!(:total_entries, {:type => ActiveSupport::CoreExtensions::Hash::Conversions::XML_TYPE_NAMES[]}, total_entries)
        end.sub(%{type="array"}, %{type="collection"})
      alias_method_chain :to_xml, :collection_type

      def serializeable_collection #:nodoc:
        # Ugly hack because to_xml will not yield the XML Builder object when empty?
        empty? ? returning(self.clone) { |c| c.instance_eval {|i| def empty?; false; end } } : self

WillPaginate::Collection.send(:include, WillPaginateHelpers)  

This now gives me the proper xml when I call to_xml

<?xml version="1.0" encoding="UTF-8"?>  
<time-cards type="collection">  
  <current_page type="integer">1</current_page>
<per_page type="integer">25</per_page>  
  <total_entries type="integer">108</total_entries>
    <approved type="boolean">false</approved>
    <billable type="boolean">false</billable>
    <created_at type="datetime">2008-10-10T14:04:13-04:00</created_at>
    <date type="datetime">2008-10-10T14:04:13-04:00</date>
    <has_been_billed type="boolean">false</has_been_billed>
    <has_been_paid type="boolean">true</has_been_paid>
    <hours type="float">2.0</hours>
    <id type="integer">98</id>
    <is_overtime type="boolean">false</is_overtime>
    <task_id type="integer">6</task_id>
    <updated_at type="datetime">2008-10-10T14:04:13-04:00</updated_at>
    <user_id type="integer">1</user_id>
comments powered by Disqus