Skip to content

Instantly share code, notes, and snippets.

@schovi
Created November 6, 2010 10:19
Show Gist options
  • Save schovi/665326 to your computer and use it in GitHub Desktop.
Save schovi/665326 to your computer and use it in GitHub Desktop.
Rail3 friendly pagination
# If you are using ActiveRecord and want to paginate it you have to write this:
# PeacefulPaginate.use_for_active_record!
# to end of your config/environment.rb
# If you want to override default .paginate method from WillPaginate gem you have to insert this
# PeacefulPaginate.use_compatible_mod_with_will_paginate!
# to end of your config/environment.rb
# With this you dont have to rewrite nothing else in your application
# In other way how to use it
# PeacefulPaginate.paginate(People.where(:city => "Prague"), :per_page => 10, :page => 2)
# or
# People.where(:city => "Prague").peaceful_paginate(:per_page => 10, :page => 2)
# It will return
# [array_with_paginated_result, hash_with_pagination_informations]
class PeacefulPaginate
module ActiveRecord
def self.included(base)
base.extend ClassMethods
end
module ClassMethods
def peaceful_paginate(options)
::PeacefulPaginate.paginate(self,options)
end
unless defined?(WillPaginate)
def paginate(options)
::PeacefulPaginate.paginate(self,options)
end
end
end
end
module OverrideWillPaginate
def self.included(base)
base.extend ClassMethods
end
module ClassMethods
def paginate(options)
::PeacefulPaginate.paginate(self,options)
end
end
end
class_eval do
unless defined? @@will_paginate_compatible_mode
@@will_paginate_compatible_mode = false
end
def self.will_paginate_compatible_mode
@@will_paginate_compatible_mode
end
def self.will_paginate_compatible_mode=(value)
@@will_paginate_compatible_mode = value
end
end
def self.paginate(object, options = {})
page = options[:page] || 1
per_page = options[:per_page] || 30
count = options[:total_entries] || options[:count]
if object.superclass == ActiveRecord::Base or object.is_a?(ActiveRecord::Relation)
scoped_object = object.scoped
if will_paginate_compatible_mode
scopes = options.except :page, :per_page, :total_entries, :count, :finder
if includes = scopes.delete(:include)
scoped_object = scoped_object.includes(includes)
end
scopes.each_pair do |scope,params|
scoped_object.send(scope, params)
end
end
paged_result = scoped_object.limit(per_page).offset((page.to_i - 1) * per_page.to_i).all
total_results_count = scoped_object.count
if will_paginate_compatible_mode
result = WillPaginate::Collection.create(page, per_page) do |pager|
pager.replace(paged_result)
pager.total_entries = total_results
end
else
result = [paged_result, {:per_page => per_page, :page => page, :count => total_results_count}]
end
elsif object.is_a?(Array)
if will_paginate_compatible_mode
result = object.paginate(:per_page => per_page,:page => page)
else
from = (page.to_i - 1) * per_page.to_i
to = from + per_page.to_i - 1
result = [object[from..to], {:per_page => per_page, :page => page, :count => object.length}]
end
else
raise "Invalid object for pagination"
end
return result
end
def self.use_for_active_record!
if defined? ::ActiveRecord
::ActiveRecord::Relation.class_eval do
include PeacefulPaginate::ActiveRecord
end
::ActiveRecord::Base.class_eval do
include PeacefulPaginate::ActiveRecord
end
true
else
false
end
end
def self.use_compatible_mod_with_will_paginate!
if defined? ::ActiveRecord and defined? WillPaginate
will_paginate_compatible_mode = true
::ActiveRecord::Relation.class_eval do
include PeacefulPaginate::OverrideWillPaginate
end
::ActiveRecord::Base.class_eval do
include PeacefulPaginate::OverrideWillPaginate
end
true
else
false
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment