Adding initial pagination support based on kaminari
This commit is contained in:
parent
6a896c27b3
commit
6723564969
|
@ -21,6 +21,8 @@ module CouchRest
|
||||||
|
|
||||||
module ClassMethods
|
module ClassMethods
|
||||||
|
|
||||||
|
# Add views and other design document features
|
||||||
|
# to the current model.
|
||||||
def design(*args, &block)
|
def design(*args, &block)
|
||||||
mapper = DesignMapper.new(self)
|
mapper = DesignMapper.new(self)
|
||||||
mapper.create_view_method(:all)
|
mapper.create_view_method(:all)
|
||||||
|
@ -30,6 +32,23 @@ module CouchRest
|
||||||
req_design_doc_refresh
|
req_design_doc_refresh
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Override the default page pagination value:
|
||||||
|
#
|
||||||
|
# class Person < CouchRest::Model::Base
|
||||||
|
# paginates_per 10
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
def paginates_per(val)
|
||||||
|
@_default_per_page = val
|
||||||
|
end
|
||||||
|
|
||||||
|
# The models number of documents to return
|
||||||
|
# by default when performing pagination.
|
||||||
|
# Returns 25 unless explicitly overridden via <tt>paginates_per</tt>
|
||||||
|
def default_per_page
|
||||||
|
@_default_per_page || 25
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|
|
@ -14,7 +14,7 @@ module CouchRest
|
||||||
class View
|
class View
|
||||||
include Enumerable
|
include Enumerable
|
||||||
|
|
||||||
attr_accessor :model, :name, :query, :result
|
attr_accessor :owner, :model, :name, :query, :result
|
||||||
|
|
||||||
# Initialize a new View object. This method should not be called from
|
# Initialize a new View object. This method should not be called from
|
||||||
# outside CouchRest Model.
|
# outside CouchRest Model.
|
||||||
|
@ -22,11 +22,13 @@ module CouchRest
|
||||||
if parent.is_a?(Class) && parent < CouchRest::Model::Base
|
if parent.is_a?(Class) && parent < CouchRest::Model::Base
|
||||||
raise "Name must be provided for view to be initialized" if name.nil?
|
raise "Name must be provided for view to be initialized" if name.nil?
|
||||||
self.model = parent
|
self.model = parent
|
||||||
|
self.owner = parent
|
||||||
self.name = name.to_s
|
self.name = name.to_s
|
||||||
# Default options:
|
# Default options:
|
||||||
self.query = { :reduce => false }
|
self.query = { :reduce => false }
|
||||||
elsif parent.is_a?(self.class)
|
elsif parent.is_a?(self.class)
|
||||||
self.model = (new_query.delete(:proxy) || parent.model)
|
self.model = (new_query.delete(:proxy) || parent.model)
|
||||||
|
self.owner = parent.owner
|
||||||
self.name = parent.name
|
self.name = parent.name
|
||||||
self.query = parent.query.dup
|
self.query = parent.query.dup
|
||||||
else
|
else
|
||||||
|
@ -174,7 +176,6 @@ module CouchRest
|
||||||
# modified appropriatly. Errors will be raised if the methods
|
# modified appropriatly. Errors will be raised if the methods
|
||||||
# are combined in an incorrect fashion.
|
# are combined in an incorrect fashion.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
|
||||||
# Find all entries in the index whose key matches the value provided.
|
# Find all entries in the index whose key matches the value provided.
|
||||||
#
|
#
|
||||||
|
@ -300,6 +301,46 @@ module CouchRest
|
||||||
@docs = nil
|
@docs = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# == Kaminari compatible pagination support
|
||||||
|
#
|
||||||
|
# Based on the really simple support for scoped pagination in the
|
||||||
|
# the Kaminari gem, we provide compatible methods here to perform
|
||||||
|
# the same actions you'd expect.
|
||||||
|
#
|
||||||
|
|
||||||
|
alias :total_count :count
|
||||||
|
|
||||||
|
def page(page)
|
||||||
|
limit(owner.default_per_page).skip(owner.default_per_page * ([page.to_i, 1].max - 1))
|
||||||
|
end
|
||||||
|
|
||||||
|
def per(num)
|
||||||
|
raise "View#page must be called before #per!" if limit_value.nil? || offset_value.nil?
|
||||||
|
if (n = num.to_i) <= 0
|
||||||
|
self
|
||||||
|
else
|
||||||
|
limit(num).skip(offset_value / limit_value * n)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def offset_value
|
||||||
|
query[:skip]
|
||||||
|
end
|
||||||
|
|
||||||
|
def limit_value
|
||||||
|
query[:limit]
|
||||||
|
end
|
||||||
|
|
||||||
|
def num_pages
|
||||||
|
(total_count.to_f / limit_value).ceil
|
||||||
|
end
|
||||||
|
|
||||||
|
def current_page
|
||||||
|
(offset_value / limit_value) + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
||||||
def include_docs!
|
def include_docs!
|
||||||
|
|
|
@ -541,6 +541,53 @@ describe "Design View" do
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "pagination methods" do
|
||||||
|
|
||||||
|
describe "#total_count" do
|
||||||
|
it "should be an alias for count" do
|
||||||
|
@obj.method(:total_count).should eql(@obj.method(:count))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#page" do
|
||||||
|
it "should call limit and skip" do
|
||||||
|
@obj.should_receive(:limit).with(25).and_return(@obj)
|
||||||
|
@obj.should_receive(:skip).with(25).and_return(@obj)
|
||||||
|
@obj.page(2)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#per" do
|
||||||
|
it "should raise an error if page not called before hand" do
|
||||||
|
lambda { @obj.per(12) }.should raise_error
|
||||||
|
end
|
||||||
|
it "should not do anything if number less than or eql 0" do
|
||||||
|
view = @obj.page(1)
|
||||||
|
view.per(0).should eql(view)
|
||||||
|
end
|
||||||
|
it "should set limit and update skip" do
|
||||||
|
view = @obj.page(2).per(10)
|
||||||
|
view.query[:skip].should eql(10)
|
||||||
|
view.query[:limit].should eql(10)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#num_pages" do
|
||||||
|
it "should use total_count and limit_value" do
|
||||||
|
@obj.should_receive(:total_count).and_return(200)
|
||||||
|
@obj.should_receive(:limit_value).and_return(25)
|
||||||
|
@obj.num_pages.should eql(8)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#current_page" do
|
||||||
|
it "should use offset and limit" do
|
||||||
|
@obj.should_receive(:offset_value).and_return(25)
|
||||||
|
@obj.should_receive(:limit_value).and_return(25)
|
||||||
|
@obj.current_page.should eql(2)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -10,31 +10,46 @@ describe "Design" do
|
||||||
DesignModel.respond_to?(:design).should be_true
|
DesignModel.respond_to?(:design).should be_true
|
||||||
end
|
end
|
||||||
|
|
||||||
describe ".design" do
|
describe "class methods" do
|
||||||
|
|
||||||
|
describe ".design" do
|
||||||
|
before :each do
|
||||||
|
@mapper = mock('DesignMapper')
|
||||||
|
@mapper.stub!(:create_view_method)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should instantiate a new DesignMapper" do
|
||||||
|
CouchRest::Model::Designs::DesignMapper.should_receive(:new).with(DesignModel).and_return(@mapper)
|
||||||
|
@mapper.should_receive(:create_view_method).with(:all)
|
||||||
|
@mapper.should_receive(:instance_eval)
|
||||||
|
DesignModel.design() { }
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should allow methods to be called in mapper" do
|
||||||
|
@mapper.should_receive(:foo)
|
||||||
|
CouchRest::Model::Designs::DesignMapper.stub!(:new).and_return(@mapper)
|
||||||
|
DesignModel.design { foo }
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should request a design refresh" do
|
||||||
|
DesignModel.should_receive(:req_design_doc_refresh)
|
||||||
|
DesignModel.design() { }
|
||||||
|
end
|
||||||
|
|
||||||
before :each do
|
|
||||||
@mapper = mock('DesignMapper')
|
|
||||||
@mapper.stub!(:create_view_method)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should instantiate a new DesignMapper" do
|
describe "default_per_page" do
|
||||||
CouchRest::Model::Designs::DesignMapper.should_receive(:new).with(DesignModel).and_return(@mapper)
|
it "should return 25 default" do
|
||||||
@mapper.should_receive(:create_view_method).with(:all)
|
DesignModel.default_per_page.should eql(25)
|
||||||
@mapper.should_receive(:instance_eval)
|
end
|
||||||
DesignModel.design() { }
|
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should allow methods to be called in mapper" do
|
describe ".paginates_per" do
|
||||||
@mapper.should_receive(:foo)
|
it "should set the default per page value" do
|
||||||
CouchRest::Model::Designs::DesignMapper.stub!(:new).and_return(@mapper)
|
DesignModel.paginates_per(21)
|
||||||
DesignModel.design { foo }
|
DesignModel.default_per_page.should eql(21)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should request a design refresh" do
|
|
||||||
DesignModel.should_receive(:req_design_doc_refresh)
|
|
||||||
DesignModel.design() { }
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "DesignMapper" do
|
describe "DesignMapper" do
|
||||||
|
|
Loading…
Reference in a new issue