Docs for pagination, not including docs in reduce and raising errors when cannot include docs
This commit is contained in:
parent
6723564969
commit
0a35be7167
3 changed files with 82 additions and 12 deletions
15
README.md
15
README.md
|
@ -364,6 +364,21 @@ You'll see that this new syntax requires all views to be defined inside a design
|
|||
puts "Tag: #{row.key} Uses: #{row.value}"
|
||||
end
|
||||
|
||||
#### Pagination
|
||||
|
||||
The view objects have built in support for pagination based on the [kaminari](https://github.com/amatsuda/kaminari) gem. Methods are provided to match those required by the library to peform pagination.
|
||||
|
||||
For your view to support paginating the results, it must use a reduce function that provides a total count of the documents in the result set. By default, auto-generated views include a reduce function that supports this.
|
||||
|
||||
Use pagination as follows:
|
||||
|
||||
# Prepare a query:
|
||||
@posts = Post.by_title.page(params[:page]).per(10)
|
||||
|
||||
# In your view, with the kaminari gem loaded:
|
||||
paginate @posts
|
||||
|
||||
|
||||
## Assocations
|
||||
|
||||
Two types at the moment:
|
||||
|
|
|
@ -249,7 +249,7 @@ module CouchRest
|
|||
# will fail.
|
||||
def reduce
|
||||
raise "Cannot reduce a view without a reduce method" unless can_reduce?
|
||||
update_query(:reduce => true)
|
||||
update_query(:reduce => true, :include_docs => nil)
|
||||
end
|
||||
|
||||
# Control whether the reduce function reduces to a set of distinct keys
|
||||
|
@ -308,8 +308,6 @@ module CouchRest
|
|||
# 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
|
||||
|
@ -323,6 +321,10 @@ module CouchRest
|
|||
end
|
||||
end
|
||||
|
||||
def total_count
|
||||
@total_count ||= limit(nil).skip(nil).count
|
||||
end
|
||||
|
||||
def offset_value
|
||||
query[:skip]
|
||||
end
|
||||
|
@ -344,6 +346,7 @@ module CouchRest
|
|||
protected
|
||||
|
||||
def include_docs!
|
||||
raise "Cannot include documents in view that has been reduced!" if query[:reduce]
|
||||
reset! if result && !include_docs?
|
||||
query[:include_docs] = true
|
||||
self
|
||||
|
@ -376,7 +379,7 @@ module CouchRest
|
|||
# Remove the reduce value if its not needed
|
||||
query.delete(:reduce) unless can_reduce?
|
||||
begin
|
||||
self.result = model.design_doc.view_on(use_database, name, query)
|
||||
self.result = model.design_doc.view_on(use_database, name, query.reject{|k,v| v.nil?})
|
||||
rescue RestClient::ResourceNotFound => e
|
||||
if retryable
|
||||
model.save_design_doc(use_database)
|
||||
|
@ -474,7 +477,7 @@ module CouchRest
|
|||
def doc
|
||||
return model.build_from_database(self['doc']) if self['doc']
|
||||
doc_id = (value.is_a?(Hash) && value['_id']) ? value['_id'] : self.id
|
||||
model.get(doc_id)
|
||||
doc_id ? model.get(doc_id) : nil
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -367,7 +367,7 @@ describe "Design View" do
|
|||
describe "#reduce" do
|
||||
it "should update query" do
|
||||
@obj.should_receive(:can_reduce?).and_return(true)
|
||||
@obj.should_receive(:update_query).with({:reduce => true})
|
||||
@obj.should_receive(:update_query).with({:reduce => true, :include_docs => nil})
|
||||
@obj.reduce
|
||||
end
|
||||
it "should raise error if query cannot be reduced" do
|
||||
|
@ -442,6 +442,10 @@ describe "Design View" do
|
|||
@obj.send(:include_docs!)
|
||||
@obj.query[:include_docs].should be_true
|
||||
end
|
||||
it "should raise an error if view is reduced" do
|
||||
@obj.query[:reduce] = true
|
||||
lambda { @obj.send(:include_docs!) }.should raise_error
|
||||
end
|
||||
end
|
||||
|
||||
describe "#include_docs?" do
|
||||
|
@ -538,17 +542,19 @@ describe "Design View" do
|
|||
lambda { @obj.send(:execute) }.should raise_error(RestClient::ResourceNotFound)
|
||||
end
|
||||
|
||||
it "should remove nil values from query" do
|
||||
@obj.should_receive(:can_reduce?).and_return(true)
|
||||
@obj.stub!(:use_database).and_return('database')
|
||||
@obj.query = {:reduce => true, :limit => nil, :skip => nil}
|
||||
@design_doc.should_receive(:view_on).with('database', 'test_view', {:reduce => true})
|
||||
@obj.send(:execute)
|
||||
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)
|
||||
|
@ -572,6 +578,16 @@ describe "Design View" do
|
|||
end
|
||||
end
|
||||
|
||||
describe "#total_count" do
|
||||
it "set limit and skip to nill and perform count" do
|
||||
@obj.should_receive(:limit).with(nil).and_return(@obj)
|
||||
@obj.should_receive(:skip).with(nil).and_return(@obj)
|
||||
@obj.should_receive(:count).and_return(5)
|
||||
@obj.total_count.should eql(5)
|
||||
@obj.total_count.should eql(5) # Second to test caching
|
||||
end
|
||||
end
|
||||
|
||||
describe "#num_pages" do
|
||||
it "should use total_count and limit_value" do
|
||||
@obj.should_receive(:total_count).and_return(200)
|
||||
|
@ -657,6 +673,15 @@ describe "Design View" do
|
|||
obj.doc.should eql(doc)
|
||||
end
|
||||
|
||||
it "should try to return nil for document if none available" do
|
||||
hash = {'value' => 23} # simulate reduce
|
||||
obj = @klass.new(hash, DesignViewModel)
|
||||
doc = mock('DesignViewModel')
|
||||
obj.model.should_not_receive(:get)
|
||||
obj.doc.should be_nil
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -708,6 +733,33 @@ describe "Design View" do
|
|||
end
|
||||
end
|
||||
|
||||
describe "pagination" do
|
||||
before :all do
|
||||
DesignViewModel.paginates_per 3
|
||||
end
|
||||
before :each do
|
||||
@view = DesignViewModel.by_name.page(1)
|
||||
end
|
||||
|
||||
it "should calculate number of pages" do
|
||||
@view.num_pages.should eql(2)
|
||||
end
|
||||
it "should return results from first page" do
|
||||
@view.all.first.name.should eql('Judith')
|
||||
@view.all.last.name.should eql('Peter')
|
||||
end
|
||||
it "should return results from second page" do
|
||||
@view.page(2).all.first.name.should eql('Sam')
|
||||
@view.page(2).all.last.name.should eql('Vilma')
|
||||
end
|
||||
|
||||
it "should allow overriding per page count" do
|
||||
@view = @view.per(10)
|
||||
@view.num_pages.should eql(1)
|
||||
@view.all.last.name.should eql('Vilma')
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue