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.
#enviroment.rb
...
require 'to_xml_extensions'
#lib/to_xml_extensions.rb
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.class.name]}, current_page)
xml.tag!(:per_page, {:type => ActiveSupport::CoreExtensions::Hash::Conversions::XML_TYPE_NAMES[per_page.class.name]}, per_page)
xml.tag!(:total_entries, {:type => ActiveSupport::CoreExtensions::Hash::Conversions::XML_TYPE_NAMES[total_entries.class.name]}, total_entries)
end.sub(%{type="array"}, %{type="collection"})
end
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
end
end
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>
<time_card>
<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>
</time_card>
...
</timecards>