[PLUGIN] ArPaginator - Allows you to easily paginate over any existing AR queries.

The built-in Rails pagination is fairly limited...you pass in the
model name, and optionally some conditions, and it generates a
paginated query for you. This gets to be very bad if you've got any
custom queries.

class Company < ActiveRecord::Base
  def complete_videos
    Video.find :all, :conditions => "company_id=#{id} AND
status='complete'", :order => "created_at DESC"
  end
end

You wouldn't be able to easily paginate over that query. You'd end up
doing something like this in your controller:

@video_pages, @videos = paginate :users, :conditions =>
"company_id=#{@company.id} AND status='complete'", :order =>
"created_at DESC"

that's obviously not DRY. You'll have to update your paginate call if
the logic of complete_videos changes, and on top of that you're
putting busines logic in the controller anyway.

ArPaginator solves this problem by letting you paginate over any
query. Using it, the new pagination code would be

paginator = ArPaginator.new(:model => :video, :controller => :videos)
@video_pages, @videos = paginator.paginate(:page => params[:page]) {
@company.complete_videos }

Now you can take any query that returns an array and paginate it easily.

ArPaginator.new takes a hash with two keys - :model and :controller.
:model is the underscored class name to be paginated. So in this case
AR ultimately calls Video.find, so we need to specify :video as the
model. The :controller option is used to specify the controller so the
call to

pagination_links @video_pages

works fine.

The API is a bit messy, and I'll be cleaning it up soon
hopefully...but the important part - easily paginating your existing
query methods - is taken care of.

One limitation is that you can't paginate over methods that use the
association proxy. So if your method was

class Company < ActiveRecord::Base
  has_many :videos

  def complete_videos
    videos.find :all, :conditions => "status='complete'", :order =>
"created_at DESC"
  end
end

then the pagination would fail. This is because Rails seems to ignore
the :limit option when using with_scope around an association proxy.
You would have to convert that code to not use the association proxy,
as in the first example.

This plugin requires the count_from_query plugin

ruby script/plugin install svn://evang.eli.st/public/plugins/count_from_query
ruby script/plugin install svn://evang.eli.st/public/plugins/ar_paginator

Released under the MIT License

Pat Maddox wrote:

The built-in Rails pagination is fairly limited...you pass in the
model name, and optionally some conditions, and it generates a
paginated query for you. This gets to be very bad if you've got any
custom queries.

class Company < ActiveRecord::Base
  def complete_videos
    Video.find :all, :conditions => "company_id=#{id} AND
status='complete'", :order => "created_at DESC"
  end
end

You wouldn't be able to easily paginate over that query. You'd end up
doing something like this in your controller:

@video_pages, @videos = paginate :users, :conditions =>
"company_id=#{@company.id} AND status='complete'", :order =>
"created_at DESC"

that's obviously not DRY. You'll have to update your paginate call if
the logic of complete_videos changes, and on top of that you're
putting busines logic in the controller anyway.

ArPaginator solves this problem by letting you paginate over any
query. Using it, the new pagination code would be

paginator = ArPaginator.new(:model => :video, :controller => :videos)
@video_pages, @videos = paginator.paginate(:page => params[:page]) {
@company.complete_videos }

Now you can take any query that returns an array and paginate it easily.

ArPaginator.new takes a hash with two keys - :model and :controller.
:model is the underscored class name to be paginated. So in this case
AR ultimately calls Video.find, so we need to specify :video as the
model. The :controller option is used to specify the controller so the
call to

pagination_links @video_pages

works fine.

The API is a bit messy, and I'll be cleaning it up soon
hopefully...but the important part - easily paginating your existing
query methods - is taken care of.

One limitation is that you can't paginate over methods that use the
association proxy. So if your method was

class Company < ActiveRecord::Base
  has_many :videos

  def complete_videos
    videos.find :all, :conditions => "status='complete'", :order =>
"created_at DESC"
  end
end

then the pagination would fail. This is because Rails seems to ignore
the :limit option when using with_scope around an association proxy.
You would have to convert that code to not use the association proxy,
as in the first example.

This plugin requires the count_from_query plugin

ruby script/plugin install svn://evang.eli.st/public/plugins/count_from_query
ruby script/plugin install svn://evang.eli.st/public/plugins/ar_paginator

Released under the MIT License

>

Elegant usage of your previous plugin :slight_smile: Very sweet.

G

Actually, the count_from_query plugin was an extraction from this one.

The middle of the paginate method had all the code that you see in
CFQ. I realized that that functionality would be generally useful as
well.

But yeah, thanks :slight_smile:

Pat