views:

157

answers:

1

I have an XML feed I am pulling down and parsing in my Rails app. I started to implement it as a library in lib/ but it seemed more logical to me to treat it as a model. For convenience I am treating it as an ActiveRecord model. A requirement is that it is compatible with mislav's will_paginate plugin, although that is where I am having the issue.

I have created a class in app/models/ that inherits from ActiveRecord::Base and simply override the default method for find. If there's an easier way I'm all ears. But this is working.

class Job < ActiveRecord::Base
  def self.columns() @columns ||= []; end

  def self.column(name, sql_type = nil, default = nil, null = true)
    columns << ActiveRecord::ConnectionAdapters::Column.new(name.to_s, default, sql_type.to_s, null)
  end

  column :title, :string
  column :company, :string

  def self.find(*args)
    url = "http://example.com"

    xml = Net::HTTP.get_response(URI.parse(url)).body
    doc = REXML::Document.new(xml)

    if args.first.to_s == 'all'
      results = Array.new

      doc.elements.each('response/results/result') do |r|
        job = self.new(
          :title => r.elements['jobtitle'].text,
          :company => r.elements['company'].text
        )

        results.push(job)
      end

      results
    end
  end
end

So with that working, the next step is try to paginate the collection. For this I am attempting to use mislav's will_paginate since I am using this plugin for my typical models. The issue is that will_paginate attempts to get a count of the number of total jobs. It does this by running a "SELECT count(*) AS count_all FROM jobs" automatically. Of course this fails since no such table exists.

Without modifying the code of will_paginate is there an easy way to correct this issue but still allow standard models to use will_paginate normally?

+1  A: 

You can quite easily make any collection paginatable(?).

Array.class_eval do
  def paginate(page = 1, per_page = 10)
    WillPaginate::Collection.create(page, per_page, size) do |pager|
      pager.replace self[pager.offset, pager.per_page].to_a
    end
  end
end

This code maps the array into the WillPaginate::Collection - the size parameter is the record count, basically.

You can either implement something similar in your model, or not use ActiveRecord ... no real reason to unless you are going to be using validations and other things down the track.

Toby Hede