Docs for pagination, not including docs in reduce and raising errors when cannot include docs
This commit is contained in:
parent
6723564969
commit
0a35be7167
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}"
|
puts "Tag: #{row.key} Uses: #{row.value}"
|
||||||
end
|
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
|
## Assocations
|
||||||
|
|
||||||
Two types at the moment:
|
Two types at the moment:
|
||||||
|
|
|
@ -249,7 +249,7 @@ module CouchRest
|
||||||
# will fail.
|
# will fail.
|
||||||
def reduce
|
def reduce
|
||||||
raise "Cannot reduce a view without a reduce method" unless can_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
|
end
|
||||||
|
|
||||||
# Control whether the reduce function reduces to a set of distinct keys
|
# Control whether the reduce function reduces to a set of distinct keys
|
||||||
|
@ -308,8 +308,6 @@ module CouchRest
|
||||||
# the same actions you'd expect.
|
# the same actions you'd expect.
|
||||||
#
|
#
|
||||||
|
|
||||||
alias :total_count :count
|
|
||||||
|
|
||||||
def page(page)
|
def page(page)
|
||||||
limit(owner.default_per_page).skip(owner.default_per_page * ([page.to_i, 1].max - 1))
|
limit(owner.default_per_page).skip(owner.default_per_page * ([page.to_i, 1].max - 1))
|
||||||
end
|
end
|
||||||
|
@ -323,6 +321,10 @@ module CouchRest
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def total_count
|
||||||
|
@total_count ||= limit(nil).skip(nil).count
|
||||||
|
end
|
||||||
|
|
||||||
def offset_value
|
def offset_value
|
||||||
query[:skip]
|
query[:skip]
|
||||||
end
|
end
|
||||||
|
@ -344,6 +346,7 @@ module CouchRest
|
||||||
protected
|
protected
|
||||||
|
|
||||||
def include_docs!
|
def include_docs!
|
||||||
|
raise "Cannot include documents in view that has been reduced!" if query[:reduce]
|
||||||
reset! if result && !include_docs?
|
reset! if result && !include_docs?
|
||||||
query[:include_docs] = true
|
query[:include_docs] = true
|
||||||
self
|
self
|
||||||
|
@ -376,7 +379,7 @@ module CouchRest
|
||||||
# Remove the reduce value if its not needed
|
# Remove the reduce value if its not needed
|
||||||
query.delete(:reduce) unless can_reduce?
|
query.delete(:reduce) unless can_reduce?
|
||||||
begin
|
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
|
rescue RestClient::ResourceNotFound => e
|
||||||
if retryable
|
if retryable
|
||||||
model.save_design_doc(use_database)
|
model.save_design_doc(use_database)
|
||||||
|
@ -474,7 +477,7 @@ module CouchRest
|
||||||
def doc
|
def doc
|
||||||
return model.build_from_database(self['doc']) if self['doc']
|
return model.build_from_database(self['doc']) if self['doc']
|
||||||
doc_id = (value.is_a?(Hash) && value['_id']) ? value['_id'] : self.id
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -367,7 +367,7 @@ describe "Design View" do
|
||||||
describe "#reduce" do
|
describe "#reduce" do
|
||||||
it "should update query" do
|
it "should update query" do
|
||||||
@obj.should_receive(:can_reduce?).and_return(true)
|
@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
|
@obj.reduce
|
||||||
end
|
end
|
||||||
it "should raise error if query cannot be reduced" do
|
it "should raise error if query cannot be reduced" do
|
||||||
|
@ -442,6 +442,10 @@ describe "Design View" do
|
||||||
@obj.send(:include_docs!)
|
@obj.send(:include_docs!)
|
||||||
@obj.query[:include_docs].should be_true
|
@obj.query[:include_docs].should be_true
|
||||||
end
|
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
|
end
|
||||||
|
|
||||||
describe "#include_docs?" do
|
describe "#include_docs?" do
|
||||||
|
@ -538,17 +542,19 @@ describe "Design View" do
|
||||||
lambda { @obj.send(:execute) }.should raise_error(RestClient::ResourceNotFound)
|
lambda { @obj.send(:execute) }.should raise_error(RestClient::ResourceNotFound)
|
||||||
end
|
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
|
end
|
||||||
|
|
||||||
describe "pagination methods" do
|
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
|
describe "#page" do
|
||||||
it "should call limit and skip" do
|
it "should call limit and skip" do
|
||||||
@obj.should_receive(:limit).with(25).and_return(@obj)
|
@obj.should_receive(:limit).with(25).and_return(@obj)
|
||||||
|
@ -572,6 +578,16 @@ describe "Design View" do
|
||||||
end
|
end
|
||||||
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
|
describe "#num_pages" do
|
||||||
it "should use total_count and limit_value" do
|
it "should use total_count and limit_value" do
|
||||||
@obj.should_receive(:total_count).and_return(200)
|
@obj.should_receive(:total_count).and_return(200)
|
||||||
|
@ -657,6 +673,15 @@ describe "Design View" do
|
||||||
obj.doc.should eql(doc)
|
obj.doc.should eql(doc)
|
||||||
end
|
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
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@ -708,6 +733,33 @@ describe "Design View" do
|
||||||
end
|
end
|
||||||
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
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue