Skip to content

Commit

Permalink
add Mongoid support
Browse files Browse the repository at this point in the history
  • Loading branch information
dbackeus authored and mislav committed Feb 4, 2013
1 parent 4c74feb commit ae4a76b
Show file tree
Hide file tree
Showing 4 changed files with 187 additions and 0 deletions.
1 change: 1 addition & 0 deletions Gemfile
Expand Up @@ -15,6 +15,7 @@ gem 'dm-core'
gem 'dm-aggregates' gem 'dm-aggregates'
gem 'dm-migrations' gem 'dm-migrations'
gem 'dm-sqlite-adapter' gem 'dm-sqlite-adapter'
gem 'mongoid'


group :mysql do group :mysql do
gem 'mysql', '~> 2.8.1' gem 'mysql', '~> 2.8.1'
Expand Down
8 changes: 8 additions & 0 deletions Gemfile.lock
Expand Up @@ -25,6 +25,7 @@ GEM
addressable (2.2.6) addressable (2.2.6)
archive-tar-minitar (0.5.2) archive-tar-minitar (0.5.2)
arel (3.0.2) arel (3.0.2)
bson (1.6.4)
builder (3.0.4) builder (3.0.4)
columnize (0.3.5) columnize (0.3.5)
data_objects (0.10.7) data_objects (0.10.7)
Expand Down Expand Up @@ -53,6 +54,12 @@ GEM
linecache19 (0.5.12) linecache19 (0.5.12)
ruby_core_source (>= 0.1.4) ruby_core_source (>= 0.1.4)
mocha (0.9.12) mocha (0.9.12)
mongo (1.6.2)
bson (~> 1.6.2)
mongoid (2.4.11)
activemodel (~> 3.1)
mongo (<= 1.6.2)
tzinfo (~> 0.3.22)
multi_json (1.5.0) multi_json (1.5.0)
mysql (2.8.1) mysql (2.8.1)
mysql2 (0.3.11) mysql2 (0.3.11)
Expand Down Expand Up @@ -111,6 +118,7 @@ DEPENDENCIES
dm-migrations dm-migrations
dm-sqlite-adapter dm-sqlite-adapter
mocha (~> 0.9.8) mocha (~> 0.9.8)
mongoid
mysql (~> 2.8.1) mysql (~> 2.8.1)
mysql2 (>= 0.3.6) mysql2 (>= 0.3.6)
pg (~> 0.11) pg (~> 0.11)
Expand Down
46 changes: 46 additions & 0 deletions lib/will_paginate/mongoid.rb
@@ -0,0 +1,46 @@
require 'mongoid'
require 'will_paginate/collection'

module WillPaginate
module Mongoid
module CriteriaMethods
def paginate(options = {})
extend CollectionMethods
@current_page = WillPaginate::PageNumber(options[:page] || @current_page || 1)
@page_multiplier = current_page - 1
pp = (options[:per_page] || per_page || WillPaginate.per_page).to_i
limit(pp).skip(@page_multiplier * pp)
end

def per_page(value = :non_given)
if value == :non_given
options[:limit] == 0 ? nil : options[:limit] # in new Mongoid versions a nil limit is saved as 0
else
limit(value)
end
end

def page(page)
paginate(:page => page)
end
end

module CollectionMethods
attr_reader :current_page

def total_entries
@total_entries ||= count
end

def total_pages
(total_entries / per_page.to_f).ceil
end

def offset
@page_multiplier * per_page
end
end

::Mongoid::Criteria.send(:include, CriteriaMethods)
end
end
132 changes: 132 additions & 0 deletions spec/finders/mongoid_spec.rb
@@ -0,0 +1,132 @@
require 'spec_helper'
require 'will_paginate/mongoid'

Mongoid.database = Mongo::Connection.new.db('will_paginate_test')

class MongoidModel
include Mongoid::Document
end

describe WillPaginate::Mongoid do
before(:all) do
MongoidModel.delete_all
4.times { MongoidModel.create! }
end

let(:criteria) { MongoidModel.criteria }

describe "#page" do
it "should forward to the paginate method" do
criteria.expects(:paginate).with(:page => 2).returns("itself")
criteria.page(2).should == "itself"
end

it "should not override per_page if set earlier in the chain" do
criteria.paginate(:per_page => 10).page(1).per_page.should == 10
criteria.paginate(:per_page => 20).page(1).per_page.should == 20
end
end

describe "#per_page" do
it "should set the limit if given an argument" do
criteria.per_page(10).options[:limit].should == 10
end

it "should return the current limit if no argument is given" do
criteria.per_page.should == nil
criteria.per_page(10).per_page.should == 10
end

it "should be interchangable with limit" do
criteria.limit(15).per_page.should == 15
end

it "should be nil'able" do
criteria.per_page(nil).per_page.should be_nil
end
end

describe "#paginate" do
it "should use criteria" do
criteria.paginate.should be_instance_of(::Mongoid::Criteria)
end

it "should not override page number if set earlier in the chain" do
criteria.page(3).paginate.current_page.should == 3
end

it "should limit according to per_page parameter" do
criteria.paginate(:per_page => 10).options.should include(:limit => 10)
end

it "should skip according to page and per_page parameters" do
criteria.paginate(:page => 2, :per_page => 5).options.should include(:skip => 5)
end

specify "first fallback value for per_page option is the current limit" do
criteria.limit(12).paginate.options.should include(:limit => 12)
end

specify "second fallback value for per_page option is WillPaginate.per_page" do
criteria.paginate.options.should include(:limit => WillPaginate.per_page)
end

specify "page should default to 1" do
criteria.paginate.options.should include(:skip => 0)
end

it "should convert strings to integers" do
criteria.paginate(:page => "2", :per_page => "3").options.should include(:limit => 3, :limit => 3)
end

describe "collection compatibility" do
describe "#total_count" do
it "should be calculated correctly" do
criteria.paginate(:per_page => 1).total_entries.should == 4
criteria.paginate(:per_page => 3).total_entries.should == 4
end

it "should be cached" do
criteria.expects(:count).once.returns(123)
criteria.paginate
2.times { criteria.total_entries.should == 123 }
end
end

it "should calculate total_pages" do
criteria.paginate(:per_page => 1).total_pages.should == 4
criteria.paginate(:per_page => 3).total_pages.should == 2
criteria.paginate(:per_page => 10).total_pages.should == 1
end

it "should return per_page" do
criteria.paginate(:per_page => 1).per_page.should == 1
criteria.paginate(:per_page => 5).per_page.should == 5
end

describe "#current_page" do
it "should return current_page" do
criteria.paginate(:page => 1).current_page.should == 1
criteria.paginate(:page => 3).current_page.should == 3
end

it "should be casted to PageNumber" do
criteria.paginate(:page => 1).current_page.should be_instance_of(WillPaginate::PageNumber)
end
end

it "should return offset" do
criteria.paginate(:page => 1).offset.should == 0
criteria.paginate(:page => 2, :per_page => 5).offset.should == 5
criteria.paginate(:page => 3, :per_page => 10).offset.should == 20
end

it "should not pollute plain mongoid criterias" do
%w(total_entries total_pages current_page).each do |method|
criteria.should_not respond_to(method)
end
criteria.offset.should be_nil # this is already a criteria method
end
end
end
end

0 comments on commit ae4a76b

Please sign in to comment.