mirror of
https://github.com/kaminari/kaminari.git
synced 2022-11-09 13:44:37 -05:00
- basic dm pagination working
This commit is contained in:
parent
5de1a974f4
commit
4b2e2042e2
5 changed files with 289 additions and 1 deletions
|
@ -26,6 +26,10 @@ Gem::Specification.new do |s|
|
||||||
s.add_development_dependency 'sqlite3', ['>= 0']
|
s.add_development_dependency 'sqlite3', ['>= 0']
|
||||||
s.add_development_dependency 'mongoid', ['>= 2']
|
s.add_development_dependency 'mongoid', ['>= 2']
|
||||||
s.add_development_dependency 'mongo_mapper', ['>= 0.9']
|
s.add_development_dependency 'mongo_mapper', ['>= 0.9']
|
||||||
|
s.add_development_dependency 'dm-core', ['>= 1.1.0']
|
||||||
|
s.add_development_dependency 'dm-migrations', ['>= 1.1.0']
|
||||||
|
s.add_development_dependency 'dm-aggregates', ['>= 1.1.0']
|
||||||
|
s.add_development_dependency 'dm-sqlite-adapter', ['>= 1.1.0']
|
||||||
s.add_development_dependency 'rspec', ['>= 0']
|
s.add_development_dependency 'rspec', ['>= 0']
|
||||||
s.add_development_dependency 'rspec-rails', ['>= 0']
|
s.add_development_dependency 'rspec-rails', ['>= 0']
|
||||||
s.add_development_dependency 'rr', ['>= 0']
|
s.add_development_dependency 'rr', ['>= 0']
|
||||||
|
|
67
lib/kaminari/models/data_mapper_extension.rb
Normal file
67
lib/kaminari/models/data_mapper_extension.rb
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
|
||||||
|
module Kaminari
|
||||||
|
module DataMapperExtension
|
||||||
|
|
||||||
|
#
|
||||||
|
module PageScopeMethods
|
||||||
|
include ::Kaminari::PageScopeMethods::InstanceMethods
|
||||||
|
|
||||||
|
# Specify the <tt>per_page</tt> value for the preceding <tt>page</tt> scope
|
||||||
|
# Model.page(3).per(10)
|
||||||
|
def per(num)
|
||||||
|
num = num.to_i
|
||||||
|
if num <= 0
|
||||||
|
self
|
||||||
|
else
|
||||||
|
#col = model.all(query.options.except(:limit,:offset).merge(:limit => num, :offset => offset_value / limit_value * num))
|
||||||
|
col = model.all(query.options.merge(:limit => num, :offset => offset_value / limit_value * num))
|
||||||
|
col.send :extend, PageScopeMethods
|
||||||
|
col
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def limit_value
|
||||||
|
query.limit
|
||||||
|
end
|
||||||
|
|
||||||
|
def offset_value
|
||||||
|
query.offset
|
||||||
|
end
|
||||||
|
|
||||||
|
def total_count
|
||||||
|
model.count(query.options.except(:limit,:offset,:order))
|
||||||
|
end
|
||||||
|
|
||||||
|
def all(options={})
|
||||||
|
col = super(options)
|
||||||
|
col.send :extend, PageScopeMethods
|
||||||
|
col
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
module Paginatable
|
||||||
|
def page(num)
|
||||||
|
num = [num.to_i, 1].max - 1
|
||||||
|
collection = all(:limit => default_per_page, :offset => default_per_page * num)
|
||||||
|
collection.send :extend, PageScopeMethods
|
||||||
|
collection
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
# This should be included into DataMapper::Collection.
|
||||||
|
# MyModel.all.class #=> DataMapper::Collection
|
||||||
|
module CollectionInstanceMethods
|
||||||
|
include Paginatable
|
||||||
|
end
|
||||||
|
|
||||||
|
# This should be included into DataMapper::Model so that one can call:
|
||||||
|
# MyModel.page #=> DataMapper::Collection
|
||||||
|
module ModelClassMethods
|
||||||
|
include Paginatable
|
||||||
|
include Kaminari::ConfigurationMethods::ClassMethods
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
|
@ -2,6 +2,7 @@ require 'rails'
|
||||||
# ensure ORMs are loaded *before* initializing Kaminari
|
# ensure ORMs are loaded *before* initializing Kaminari
|
||||||
begin; require 'mongoid'; rescue LoadError; end
|
begin; require 'mongoid'; rescue LoadError; end
|
||||||
begin; require 'mongo_mapper'; rescue LoadError; end
|
begin; require 'mongo_mapper'; rescue LoadError; end
|
||||||
|
begin; require 'dm-core'; require 'dm-aggregates'; rescue LoadError; end
|
||||||
|
|
||||||
require File.join(File.dirname(__FILE__), 'config')
|
require File.join(File.dirname(__FILE__), 'config')
|
||||||
require File.join(File.dirname(__FILE__), 'helpers/action_view_extension')
|
require File.join(File.dirname(__FILE__), 'helpers/action_view_extension')
|
||||||
|
@ -27,6 +28,10 @@ module Kaminari
|
||||||
::Plucky::Query.send :include, Kaminari::PluckyCriteriaMethods
|
::Plucky::Query.send :include, Kaminari::PluckyCriteriaMethods
|
||||||
::Plucky::Query.send :include, Kaminari::PageScopeMethods
|
::Plucky::Query.send :include, Kaminari::PageScopeMethods
|
||||||
end
|
end
|
||||||
|
if defined? ::DataMapper
|
||||||
|
require File.join(File.dirname(__FILE__), 'models/data_mapper_extension')
|
||||||
|
::DataMapper::Collection.send :include, Kaminari::DataMapperExtension::CollectionInstanceMethods
|
||||||
|
end
|
||||||
require File.join(File.dirname(__FILE__), 'models/array_extension')
|
require File.join(File.dirname(__FILE__), 'models/array_extension')
|
||||||
ActiveSupport.on_load(:action_view) do
|
ActiveSupport.on_load(:action_view) do
|
||||||
::ActionView::Base.send :include, Kaminari::ActionViewExtension
|
::ActionView::Base.send :include, Kaminari::ActionViewExtension
|
||||||
|
|
211
spec/models/data_mapper_spec.rb
Normal file
211
spec/models/data_mapper_spec.rb
Normal file
|
@ -0,0 +1,211 @@
|
||||||
|
require File.expand_path('../spec_helper', File.dirname(__FILE__))
|
||||||
|
require 'dm-core'
|
||||||
|
require 'dm-migrations'
|
||||||
|
require 'dm-aggregates'
|
||||||
|
require File.expand_path('../../lib/kaminari/models/data_mapper_extension', File.dirname(__FILE__))
|
||||||
|
|
||||||
|
describe Kaminari::DataMapperExtension do
|
||||||
|
before :all do
|
||||||
|
|
||||||
|
DataMapper.setup(:default, 'sqlite::memory:')
|
||||||
|
|
||||||
|
class Worker
|
||||||
|
include ::DataMapper::Resource
|
||||||
|
|
||||||
|
property :id, Serial
|
||||||
|
property :name, String, :required => true
|
||||||
|
property :age, Integer, :required => true
|
||||||
|
|
||||||
|
has n, :projects, :through => Resource
|
||||||
|
end
|
||||||
|
|
||||||
|
class Project
|
||||||
|
include ::DataMapper::Resource
|
||||||
|
|
||||||
|
property :id, Serial
|
||||||
|
property :name, String, :required => true
|
||||||
|
|
||||||
|
has n, :workers, :through => Resource
|
||||||
|
end
|
||||||
|
|
||||||
|
DataMapper.finalize
|
||||||
|
DataMapper.auto_migrate!
|
||||||
|
|
||||||
|
::DataMapper::Model.append_extensions Kaminari::DataMapperExtension::ModelClassMethods
|
||||||
|
|
||||||
|
300.times do |i|
|
||||||
|
Worker.create(:name => "Worker#{i}", :age => i)
|
||||||
|
end
|
||||||
|
|
||||||
|
worker0 = Worker[0]
|
||||||
|
50.times do |i|
|
||||||
|
worker0.projects << Project.create(:name => "Project#{i}")
|
||||||
|
end
|
||||||
|
worker0.projects.save
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
describe Kaminari::DataMapperExtension::PageScopeMethods do
|
||||||
|
context 'has methods' do
|
||||||
|
subject{ Kaminari::DataMapperExtension::PageScopeMethods.instance_methods }
|
||||||
|
it { should include(:per) }
|
||||||
|
it { should include(:current_page) }
|
||||||
|
it { should include(:num_pages) }
|
||||||
|
it { should include(:limit_value) }
|
||||||
|
it { should include(:offset_value) }
|
||||||
|
it { should include(:total_count) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
#describe Kaminari::DataMapperExtension::Paginatable do
|
||||||
|
# context 'has methods' do
|
||||||
|
# subject{ Kaminari::DataMapperExtension::Paginatable.instance_methods }
|
||||||
|
# it { should include(:page) }
|
||||||
|
# end
|
||||||
|
#end
|
||||||
|
|
||||||
|
#shared_examples_for Kaminari::DataMapperExtension::Paginatable do
|
||||||
|
# context 'has methods' do
|
||||||
|
# subject{ Kaminari::DataMapperExtension::Paginatable.instance_methods }
|
||||||
|
# it { should include(:page) }
|
||||||
|
# end
|
||||||
|
#end
|
||||||
|
|
||||||
|
#describe Kaminari::DataMapperExtension::CollectionInstanceMethods do
|
||||||
|
# it_behaves_like Kaminari::DataMapperExtension::Paginatable
|
||||||
|
#end
|
||||||
|
|
||||||
|
#describe Kaminari::DataMapperExtension::ModelClassMethods do
|
||||||
|
# it_behaves_like Kaminari::DataMapperExtension::Paginatable
|
||||||
|
#end
|
||||||
|
|
||||||
|
describe 'Collection' do
|
||||||
|
subject{ Worker.all }
|
||||||
|
it { should respond_to(:page) }
|
||||||
|
it { should_not respond_to(:per) }
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'Model' do
|
||||||
|
subject{ Worker }
|
||||||
|
it { should respond_to(:page) }
|
||||||
|
it { should respond_to(:default_per_page) }
|
||||||
|
it { should_not respond_to(:per) }
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#page' do
|
||||||
|
context 'page 0' do
|
||||||
|
subject { Worker.all(:age.gte => 200).page 0 }
|
||||||
|
its(:current_page) { should == 1 }
|
||||||
|
its('query.limit') { should == 25 }
|
||||||
|
its('query.offset') { should == 0 }
|
||||||
|
its(:total_count) { should == Worker.count(:age.gte => 200) }
|
||||||
|
its(:num_pages) { should == 4 }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'page 1' do
|
||||||
|
subject { Worker.all(:age.gte => 0).page 1 }
|
||||||
|
its(:current_page) { should == 1 }
|
||||||
|
its('query.limit') { should == 25 }
|
||||||
|
its('query.offset') { should == 0 }
|
||||||
|
its(:total_count) { should == 300 }
|
||||||
|
its(:num_pages) { should == 12 }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'page 2' do
|
||||||
|
subject { Worker.page 2 }
|
||||||
|
its(:current_page) { should == 2 }
|
||||||
|
its('query.limit') { should == 25 }
|
||||||
|
its('query.offset') { should == 25 }
|
||||||
|
its(:total_count) { should == 300 }
|
||||||
|
its(:num_pages) { should == 12 }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'page "foobar"' do
|
||||||
|
subject { Worker.page 'foobar' }
|
||||||
|
its(:current_page) { should == 1 }
|
||||||
|
its('query.limit') { should == 25 }
|
||||||
|
its('query.offset') { should == 0 }
|
||||||
|
its(:total_count) { should == 300 }
|
||||||
|
its(:num_pages) { should == 12 }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with criteria before' do
|
||||||
|
subject { Worker.all(:age.gt => 100).page 2 }
|
||||||
|
#its('query.conditions') { should == {:age.gt => 1} }
|
||||||
|
its(:current_page) { should == 2 }
|
||||||
|
its('query.limit') { should == 25 }
|
||||||
|
its('query.offset') { should == 25 }
|
||||||
|
its(:total_count) { should == Worker.count(:age.gt => 100) }
|
||||||
|
its(:num_pages) { should == 8 }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with criteria after' do
|
||||||
|
subject { Worker.page(2).all(:age.gt => 100) }
|
||||||
|
#its('query.conditions') { should == {:age.gt => 100} }
|
||||||
|
its(:current_page) { should == 2 }
|
||||||
|
its('query.limit') { should == 25 }
|
||||||
|
its('query.offset') { should == 25 }
|
||||||
|
its(:total_count) { should == Worker.count(:age.gt => 100) }
|
||||||
|
its(:num_pages) { should == 8 }
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#per' do
|
||||||
|
context 'on simple query' do
|
||||||
|
subject { Worker.page(2).per(10) }
|
||||||
|
its(:current_page) { should == 2 }
|
||||||
|
its('query.limit') { should == 10 }
|
||||||
|
its('query.offset') { should == 10 }
|
||||||
|
its(:total_count) { should == 300 }
|
||||||
|
its(:num_pages) { should == 30 }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'on query with condition' do
|
||||||
|
subject { Worker.page(5).all(:age.lte => 100).per(13) }
|
||||||
|
its(:current_page) { should == 5 }
|
||||||
|
its('query.limit') { should == 13 }
|
||||||
|
its('query.offset') { should == 52 }
|
||||||
|
its(:total_count) { should == 101 }
|
||||||
|
its(:num_pages) { should == 8 }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'on query with order' do
|
||||||
|
subject { Worker.page(5).all(:age.lte => 100, :order => [:age.asc]).per(13) }
|
||||||
|
its(:current_page) { should == 5 }
|
||||||
|
its('query.limit') { should == 13 }
|
||||||
|
its('query.offset') { should == 52 }
|
||||||
|
its(:total_count) { should == 101 }
|
||||||
|
its(:num_pages) { should == 8 }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'on chained queries' do
|
||||||
|
subject { Worker.all(:age.gte => 50).page(3).all(:age.lte => 100).per(13) }
|
||||||
|
its(:current_page) { should == 3 }
|
||||||
|
its('query.limit') { should == 13 }
|
||||||
|
its('query.offset') { should == 26 }
|
||||||
|
its(:total_count) { should == 51 }
|
||||||
|
its(:num_pages) { should == 4 }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'on query on association' do
|
||||||
|
subject { Worker[0].projects.page(3).all(:name.like => 'Project%').per(5) }
|
||||||
|
its(:current_page) { should == 3 }
|
||||||
|
its('query.limit') { should == 5 }
|
||||||
|
its('query.offset') { should == 10 }
|
||||||
|
its(:total_count) { should == 50 }
|
||||||
|
its(:num_pages) { should == 10 }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'on query with association conditions' do
|
||||||
|
subject { Worker.page(3).all(:projects => Project.all).per(5) }
|
||||||
|
its(:current_page) { should == 3 }
|
||||||
|
its('query.limit') { should == 5 }
|
||||||
|
its('query.offset') { should == 10 }
|
||||||
|
its(:total_count) { should == 50 }
|
||||||
|
its(:num_pages) { should == 10 }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
end
|
|
@ -2,6 +2,7 @@ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
||||||
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
||||||
require 'rails'
|
require 'rails'
|
||||||
require 'mongoid'
|
require 'mongoid'
|
||||||
|
require 'dm-core'
|
||||||
require 'kaminari'
|
require 'kaminari'
|
||||||
require 'database_cleaner'
|
require 'database_cleaner'
|
||||||
# Ensure we use 'syck' instead of 'psych' in 1.9.2
|
# Ensure we use 'syck' instead of 'psych' in 1.9.2
|
||||||
|
|
Loading…
Reference in a new issue