neat-pages 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in neat-pages.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,7 @@
1
+ Copyright (c) 2012 De Marque inc.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,31 @@
1
+ Neat Pages [![Build Status](https://secure.travis-ci.org/demarque/neat-pages.png?branch=master)](http://travis-ci.org/demarque/neat-pages)
2
+ ===============
3
+
4
+ A simple pagination API to paginate Mongoid Models or any other stuff...
5
+
6
+ Install
7
+ -------
8
+
9
+ ```
10
+ gem install neat-pages
11
+ ```
12
+
13
+ Rails 3
14
+ -------
15
+
16
+ In your Gemfile:
17
+
18
+ ```ruby
19
+ gem 'neat-pages'
20
+ ```
21
+
22
+ Usage
23
+ -----
24
+
25
+ COMING SOON
26
+
27
+
28
+ Copyright
29
+ ---------
30
+
31
+ Copyright (c) 2012 De Marque inc. See LICENSE for further details.
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ require "bundler"
2
+ require "rspec/core/rake_task"
3
+
4
+ Bundler::GemHelper.install_tasks
5
+
6
+ desc "Run all specs in spec directory"
7
+ RSpec::Core::RakeTask.new(:spec) do |spec|
8
+ spec.pattern = "spec/**/*_spec.rb"
9
+ end
10
+
11
+ task :default => :spec
data/lib/neat-pages.rb ADDED
@@ -0,0 +1,8 @@
1
+ module NeatPages
2
+
3
+ end
4
+
5
+ require 'neat_pages/base'
6
+ require 'neat_pages/helpers'
7
+ require 'neat_pages/errors'
8
+ require 'neat_pages/implants'
@@ -0,0 +1,117 @@
1
+ module NeatPages
2
+ #*************************************************************************************
3
+ # TOCOMMENT
4
+ #*************************************************************************************
5
+ class Base
6
+ attr_accessor :per_page
7
+ attr_reader :current_page
8
+ attr_reader :total_items
9
+
10
+ #*************************************************************************************
11
+ # CONSTRUCTOR
12
+ #*************************************************************************************
13
+ def initialize(current_page, options={})
14
+ options = { :per_page => 10, :total_items => 0 }.merge(options)
15
+
16
+ @per_page = options[:per_page].to_i
17
+ @total_items = options[:total_items]
18
+
19
+ @current_page = init_current_page(current_page)
20
+
21
+ @out_of_bound = init_out_of_bound
22
+ end
23
+
24
+
25
+ #*************************************************************************************
26
+ # PUBLIC INSTANCE METHODS
27
+ #*************************************************************************************
28
+ def activate_helpers(base_url='', params={})
29
+ @helpers = NeatPages::Helpers.new(self, base_url, params)
30
+ end
31
+
32
+ def empty?
33
+ @total_items == 0
34
+ end
35
+
36
+ def helpers
37
+ if @helpers
38
+ @helpers
39
+ else
40
+ raise 'You must activate the helpers by calling "activate_helpers".'
41
+ end
42
+ end
43
+
44
+ alias_method :h, :helpers
45
+
46
+ def limit
47
+ @per_page
48
+ end
49
+
50
+ def next_page
51
+ next? ? (@current_page + 1) : total_pages
52
+ end
53
+
54
+ def next?
55
+ @current_page < total_pages and not out_of_bound?
56
+ end
57
+
58
+ def offset
59
+ if out_of_bound?
60
+ total_items + 1
61
+ else
62
+ (@current_page - 1) * @per_page
63
+ end
64
+ end
65
+
66
+ def out_of_bound?
67
+ @out_of_bound
68
+ end
69
+
70
+ def paginated?
71
+ @total_items > @per_page
72
+ end
73
+
74
+ def previous_page
75
+ previous? ? (@current_page - 1) : 1
76
+ end
77
+
78
+ def previous?
79
+ @current_page > 1 and not out_of_bound?
80
+ end
81
+
82
+ def response_headers
83
+ {
84
+ "X-Total-Items" => @total_items.to_s,
85
+ "X-Total-Pages" => total_pages.to_s,
86
+ "X-Per-Page" => @per_page.to_s,
87
+ "X-Current-Page" => @current_page.to_s
88
+ }
89
+ end
90
+
91
+ def set_total_items(qte)
92
+ @total_items = qte
93
+ @out_of_bound = init_out_of_bound
94
+ end
95
+
96
+ def total_pages
97
+ total = (@total_items.to_f / @per_page).ceil
98
+ total != 0 ? total : 1
99
+ end
100
+
101
+ private
102
+
103
+ #*************************************************************************************
104
+ # PRIVATE INSTANCE METHODS
105
+ #*************************************************************************************
106
+ def init_current_page(current_page)
107
+ current_page = current_page.to_i
108
+ current_page = 1 if current_page == 0
109
+
110
+ return current_page
111
+ end
112
+
113
+ def init_out_of_bound
114
+ @current_page <= 0 or @current_page > total_pages
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,4 @@
1
+ module NeatPages
2
+ class OutOfBound < StandardError
3
+ end
4
+ end
@@ -0,0 +1,75 @@
1
+ # encoding : utf-8
2
+ module NeatPages
3
+ #*************************************************************************************
4
+ # TOCOMMENT
5
+ #*************************************************************************************
6
+ class Helpers
7
+ #*************************************************************************************
8
+ # CONSTRUCTOR
9
+ #*************************************************************************************
10
+ def initialize(pagination, base_url, params)
11
+ @pagination = pagination
12
+ @base_url = base_url
13
+ @params = params
14
+ end
15
+
16
+
17
+ #*************************************************************************************
18
+ # PUBLIC INSTANCE METHODS
19
+ #*************************************************************************************
20
+ def navigation
21
+ if paginated?
22
+ content = ''
23
+ content << navigation_link('previous') if previous?
24
+ content << navigation_link('next') if next?
25
+
26
+ return "<div class=\"pagination\">#{content.html_safe}</div>".html_safe
27
+ else
28
+ return ''
29
+ end
30
+ end
31
+
32
+ def status
33
+ return '' if empty? or out_of_bound?
34
+
35
+ from = offset
36
+ to = from + per_page
37
+ to = total_items if to > total_items
38
+
39
+ return "#{from+1} #{t('to')} #{to}/#{total_items}"
40
+ end
41
+
42
+ private
43
+
44
+ #*************************************************************************************
45
+ # PRIVATE INSTANCE METHODS
46
+ #*************************************************************************************
47
+ def navigation_link(direction)
48
+ label_str = direction == 'next' ? "#{t('page_next')} »" : "« #{t('page_previous')}"
49
+
50
+ link_url = path_to(send("#{direction}_page"))
51
+
52
+ return "<a href=\"#{link_url}\" class=\"#{direction}\">#{label_str}</a>".html_safe
53
+ end
54
+
55
+ def path_to(page)
56
+ qs = ["page=#{page}"]
57
+
58
+ @params.each { |k,v| qs << "#{k}=#{v}" if k != 'page' }
59
+
60
+ return @base_url + '?' + qs.join("&")
61
+ end
62
+
63
+ def t(text_path)
64
+ (defined? I18n) ? I18n.t("neat_pages.#{text_path}") : text_path
65
+ end
66
+
67
+ def method_missing(*args, &block)
68
+ if @pagination.respond_to? args.first
69
+ return @pagination.send *args, &block
70
+ else
71
+ raise NoMethodError.new("undefined local variable or method '#{args.first}' for #{self.class}")
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,12 @@
1
+ module NeatPages
2
+ module Implants
3
+ end
4
+ end
5
+
6
+ if defined? Rails::Railtie
7
+ require 'neat_pages/implants/railtie'
8
+ elsif defined? Rails::Initializer
9
+ raise "neat-pages is not compatible with Rails 2.3 or older"
10
+ end
11
+
12
+ require 'neat_pages/implants/mongoid_implant'
@@ -0,0 +1,36 @@
1
+ module NeatPages::Implants::ActionControllerImplant
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ append_after_filter :set_pagination_header
6
+ helper_method :pagination, :pagination_helpers
7
+ rescue_from NeatPages::OutOfBound, :with => :render_out_of_bound
8
+ end
9
+
10
+ def paginate(options={})
11
+ options.reverse_merge!(:per_page => 20)
12
+
13
+ base_current_url = request.protocol + request.host + request.path_info
14
+
15
+ neat_pages = NeatPages::Base.new(params[:page], options)
16
+ neat_pages.activate_helpers(base_current_url, request.env['rack.request.query_hash'])
17
+
18
+ @_env['neat_pages'] = neat_pages
19
+ end
20
+
21
+ def pagination
22
+ @_env['neat_pages']
23
+ end
24
+
25
+ def pagination_helpers
26
+ pagination.helpers
27
+ end
28
+
29
+ def render_out_of_bound
30
+ render :text => "out_of_bound", :status => 404
31
+ end
32
+
33
+ def set_pagination_header
34
+ response.headers.merge! pagination.response_headers if pagination
35
+ end
36
+ end
@@ -0,0 +1,17 @@
1
+ module NeatPages::Implants
2
+ module MongoidCriteriaImplant
3
+ def paginate(current)
4
+ if current
5
+ current.set_total_items self.count
6
+
7
+ raise NeatPages::OutOfBound if current.out_of_bound?
8
+
9
+ return self.offset(current.offset).limit(current.limit)
10
+ else
11
+ raise 'You need to initialize the pagination'
12
+ end
13
+ end
14
+ end
15
+ end
16
+
17
+ Mongoid::Criteria.send :include, NeatPages::Implants::MongoidCriteriaImplant if defined? Mongoid
@@ -0,0 +1,13 @@
1
+ require 'neat_pages/implants/action_controller_implant'
2
+
3
+ module NeatPages::Implants
4
+ class Railtie < Rails::Railtie
5
+ initializer "neat_pages" do |app|
6
+
7
+ ActiveSupport.on_load :action_controller do
8
+ include NeatPages::Implants::ActionControllerImplant
9
+ end
10
+
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,4 @@
1
+ require 'spec_helper'
2
+
3
+ describe NeatPages do
4
+ end
@@ -0,0 +1,124 @@
1
+ require 'spec_helper'
2
+
3
+ describe NeatPages::Base do
4
+ #*************************************************************************************
5
+ # PUBLIC INSTANCE METHODS
6
+ #*************************************************************************************
7
+ describe "#empty?" do
8
+ context "with a 20 items pagination" do
9
+ specify { NeatPages::Base.new(0, :total_items => 20).should_not be_empty }
10
+ end
11
+
12
+ context "with a 0 item pagination" do
13
+ specify { NeatPages::Base.new(0).should be_empty }
14
+ end
15
+ end
16
+
17
+ describe "#next_page" do
18
+ context "with a 100 items pagination starting at 0 and having 10 items per page" do
19
+ specify { NeatPages::Base.new(0, :per_page => 10, :total_items => 100).next_page.should eql 2 }
20
+ end
21
+
22
+ context "with a 100 items pagination starting at page 3 and having 15 items per page" do
23
+ specify { NeatPages::Base.new(3, :per_page => 15, :total_items => 100).next_page.should eql 4 }
24
+ end
25
+
26
+ context "with a 5 items pagination starting at 0 and having 10 items per page" do
27
+ specify { NeatPages::Base.new(0, :per_page => 10, :total_items => 5).next_page.should eql 1 }
28
+ end
29
+ end
30
+
31
+ describe "#next?" do
32
+ context "with a 100 items pagination starting at 0 and having 10 items per page" do
33
+ specify { NeatPages::Base.new(0, :per_page => 10, :total_items => 100).should be_next }
34
+ end
35
+
36
+ context "with a 5 items pagination starting at 0 and having 10 items per page" do
37
+ specify { NeatPages::Base.new(0, :per_page => 10, :total_items => 5).should_not be_next }
38
+ end
39
+ end
40
+
41
+ describe "#offset" do
42
+ context "with a 100 items pagination starting at page 1 and having 10 items per page" do
43
+ specify { NeatPages::Base.new(1, :per_page => 10, :total_items => 100).offset.should eql 0 }
44
+ end
45
+
46
+ context "with a 100 items pagination starting at page 4 and having 15 items per page" do
47
+ specify { NeatPages::Base.new(4, :per_page => 15, :total_items => 100).offset.should eql 45 }
48
+ end
49
+
50
+ context "with a 100 items pagination starting at page 999 and having 15 items per page" do
51
+ specify { NeatPages::Base.new(999, :per_page => 15, :total_items => 100).offset.should eql 101 }
52
+ end
53
+ end
54
+
55
+ describe "#out_of_bound?" do
56
+ context "with a 100 items pagination starting at page 1 and having 10 items per page" do
57
+ specify { NeatPages::Base.new(1, :per_page => 10, :total_items => 100).should_not be_out_of_bound }
58
+ end
59
+
60
+ context "with a 100 items pagination starting at page 11 and having 10 items per page" do
61
+ specify { NeatPages::Base.new(11, :per_page => 10, :total_items => 100).should be_out_of_bound }
62
+ end
63
+ end
64
+
65
+ describe "#previous_page" do
66
+ context "with a 100 items pagination starting at page 5 and having 10 items per page" do
67
+ specify { NeatPages::Base.new(5, :per_page => 10, :total_items => 100).previous_page.should eql 4 }
68
+ end
69
+
70
+ context "with a 100 items pagination starting at page 3 and having 15 items per page" do
71
+ specify { NeatPages::Base.new(3, :per_page => 15, :total_items => 100).previous_page.should eql 2 }
72
+ end
73
+
74
+ context "with a 50 items pagination starting at 0 and having 10 items per page" do
75
+ specify { NeatPages::Base.new(0, :per_page => 10, :total_items => 50).previous_page.should eql 1 }
76
+ end
77
+ end
78
+
79
+ describe "#previous" do
80
+ context "with a 100 items pagination starting at page 5 and having 10 items per page" do
81
+ specify { NeatPages::Base.new(5, :per_page => 10, :total_items => 100).should be_previous }
82
+ end
83
+
84
+ context "with a 50 items pagination starting at 0 and having 10 items per page" do
85
+ specify { NeatPages::Base.new(0, :per_page => 10, :total_items => 50).should_not be_previous }
86
+ end
87
+ end
88
+
89
+ describe "#previous?" do
90
+ context "with a 100 items pagination starting at 0 and having 10 items per page" do
91
+ specify { NeatPages::Base.new(0, :per_page => 10, :total_items => 100).should_not be_previous }
92
+ end
93
+
94
+ context "with a 100 items pagination starting at page 2 and having 10 items per page" do
95
+ specify { NeatPages::Base.new(2, :per_page => 10, :total_items => 100).should be_previous }
96
+ end
97
+
98
+ context "with a 5 items pagination starting at 0 and having 10 items per page" do
99
+ specify { NeatPages::Base.new(0, :per_page => 10, :total_items => 5).should_not be_previous }
100
+ end
101
+ end
102
+
103
+ describe "#response_headers" do
104
+ context "with a 200 items pagination starting at page 1 and having 10 items per page" do
105
+ subject { NeatPages::Base.new(1, :per_page => 10, :total_items => 200).response_headers }
106
+
107
+ its(:length) { should eql 4 }
108
+ its(['X-Total-Items']) { should eql '200' }
109
+ its(['X-Total-Pages']) { should eql '20' }
110
+ its(['X-Per-Page']) { should eql '10' }
111
+ its(['X-Current-Page']) { should eql '1' }
112
+ end
113
+ end
114
+
115
+ describe "#total_pages" do
116
+ context "with a 100 items pagination and having 10 items per page" do
117
+ specify { NeatPages::Base.new(0, :per_page => 10, :total_items => 100).total_pages.should eql 10 }
118
+ end
119
+
120
+ context "with a 0 items pagination and having 10 items per page" do
121
+ specify { NeatPages::Base.new(0, :per_page => 10).total_pages.should eql 1 }
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,29 @@
1
+ require 'spec_helper'
2
+
3
+ describe NeatPages::Helpers do
4
+ describe "#status" do
5
+ context "with a 100 items pagination starting at 0 and having 10 items per page" do
6
+ let(:neat_pages) { NeatPages::Base.new(0, :per_page => 10, :total_items => 100) }
7
+
8
+ before { neat_pages.activate_helpers }
9
+
10
+ specify { neat_pages.helpers.status.should eql "1 to 10/100" }
11
+ end
12
+
13
+ context "with a 23 items pagination starting at page 3 and having 10 items per page" do
14
+ let(:neat_pages) { NeatPages::Base.new(3, :per_page => 10, :total_items => 23) }
15
+
16
+ before { neat_pages.activate_helpers }
17
+
18
+ specify { neat_pages.helpers.status.should eql "21 to 23/23" }
19
+ end
20
+
21
+ context "with a 0 items pagination starting at 0 and having 10 items per page" do
22
+ let(:neat_pages) { NeatPages::Base.new(0, :per_page => 10, :total_items => 0) }
23
+
24
+ before { neat_pages.activate_helpers }
25
+
26
+ specify { neat_pages.helpers.status.should be_empty }
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,12 @@
1
+ require "rubygems"
2
+ require "bundler/setup"
3
+
4
+ require 'rspec'
5
+
6
+ require File.expand_path('../../lib/neat-pages', __FILE__)
7
+
8
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
9
+
10
+ RSpec.configure do |config|
11
+ config.mock_with :rspec
12
+ end
metadata ADDED
@@ -0,0 +1,86 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: neat-pages
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Sebastien Rosa
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-05-10 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rake
16
+ requirement: &2164478480 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 0.8.7
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: *2164478480
25
+ - !ruby/object:Gem::Dependency
26
+ name: rspec
27
+ requirement: &2164477640 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '2.0'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *2164477640
36
+ description: ''
37
+ email:
38
+ - sebastien@demarque.com
39
+ executables: []
40
+ extensions: []
41
+ extra_rdoc_files:
42
+ - LICENSE
43
+ - README.md
44
+ files:
45
+ - lib/neat-pages.rb
46
+ - lib/neat_pages/base.rb
47
+ - lib/neat_pages/errors.rb
48
+ - lib/neat_pages/helpers.rb
49
+ - lib/neat_pages/implants/action_controller_implant.rb
50
+ - lib/neat_pages/implants/mongoid_implant.rb
51
+ - lib/neat_pages/implants/railtie.rb
52
+ - lib/neat_pages/implants.rb
53
+ - spec/neat-pages_spec.rb
54
+ - spec/neat_pages/base_spec.rb
55
+ - spec/neat_pages/helpers_spec.rb
56
+ - spec/spec_helper.rb
57
+ - LICENSE
58
+ - README.md
59
+ - Rakefile
60
+ - Gemfile
61
+ homepage: https://github.com/demarque/neat-pages
62
+ licenses:
63
+ - MIT
64
+ post_install_message:
65
+ rdoc_options: []
66
+ require_paths:
67
+ - lib
68
+ required_ruby_version: !ruby/object:Gem::Requirement
69
+ none: false
70
+ requirements:
71
+ - - ! '>='
72
+ - !ruby/object:Gem::Version
73
+ version: '0'
74
+ required_rubygems_version: !ruby/object:Gem::Requirement
75
+ none: false
76
+ requirements:
77
+ - - ! '>='
78
+ - !ruby/object:Gem::Version
79
+ version: '0'
80
+ requirements: []
81
+ rubyforge_project: neat-pages
82
+ rubygems_version: 1.8.17
83
+ signing_key:
84
+ specification_version: 3
85
+ summary: ''
86
+ test_files: []