dm-paginator 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Juan Felipe Alvarez Saldarriaga
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,17 @@
1
+ = dm-paginator
2
+
3
+ A simple paginator for ruby's DataMapper.
4
+
5
+ == Note on Patches/Pull Requests
6
+
7
+ * Fork the project.
8
+ * Make your feature addition or bug fix.
9
+ * Add tests for it. This is important so I don't break it in a
10
+ future version unintentionally.
11
+ * Commit, do not mess with rakefile, version, or history.
12
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
13
+ * Send me a pull request. Bonus points for topic branches.
14
+
15
+ == Copyright
16
+
17
+ Copyright (c) 2010 Juan Felipe Alvarez Saldarriaga. See LICENSE for details.
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env ruby1.8
2
+ require "rubygems"
3
+ require "dm-core"
4
+ require "dm-paginator"
5
+
6
+ class Item
7
+ include DataMapper::Resource
8
+ property :id, Serial
9
+ end
10
+
11
+ DataMapper.setup :default, "sqlite3::memory:"
12
+ DataMapper.auto_migrate!
13
+ ( 1..10 ).each { | n | Item.create }
14
+
15
+ def test_paginator
16
+ @items = Item.limit_page nil, :limit => 2
17
+ p "<ul>"
18
+ @items.each do | item |
19
+ p "<li>" + item.id.to_s + "</li>"
20
+ end
21
+ p "</ul>"
22
+
23
+ p "page: " + @items.paginator.page.to_s
24
+ p "count: " + @items.paginator.count.to_s
25
+ p "page_count: " + @items.paginator.page_count.to_s
26
+
27
+ p @items.paginator.to_html "All", "control.erb"
28
+ end
29
+
30
+ test_paginator
@@ -0,0 +1,15 @@
1
+ require "dm-core"
2
+ require "erb"
3
+ require "dm-paginator/paginator"
4
+ require "dm-paginator/default"
5
+ require "dm-paginator/main"
6
+ require "dm-paginator/control"
7
+ require "dm-paginator/control/control_helper_abstract"
8
+ require "dm-paginator/control/all"
9
+ require "dm-paginator/control/sliding"
10
+ require "dm-paginator/control/elastic"
11
+ require "dm-paginator/control/jumping"
12
+
13
+ DataMapper::Model.append_extensions DataMapper::Paginator
14
+ DataMapper::Collection.send :include, DataMapper::Paginator
15
+ DataMapper::Query.send :include, DataMapper::Paginator
@@ -0,0 +1,31 @@
1
+ module DataMapper
2
+ module Paginator
3
+ class Control
4
+ class << self; protected :new; end
5
+
6
+ ##
7
+ # Factory.
8
+ #
9
+ # @param [Main] paginator
10
+ # @param [String] kind
11
+ # @param [Hash] options
12
+ # @return [Sliding|Elastic|Jumping|All]
13
+ def self.factory paginator, kind = nil, options = {}
14
+ if !paginator.is_a?( Main )
15
+ raise ArgumentError, "paginator argument is not an instance of Main"
16
+ end
17
+
18
+ case kind.downcase!
19
+ when "sliding"
20
+ return DataMapper::Paginator::ControlHelper::Sliding.new paginator, options
21
+ when "elastic"
22
+ return DataMapper::Paginator::ControlHelper::Elastic.new paginator, options
23
+ when "jumping"
24
+ return DataMapper::Paginator::ControlHelper::Jumping.new paginator, options
25
+ when "all", kind.empty?
26
+ return DataMapper::Paginator::ControlHelper::All.new paginator, options
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,25 @@
1
+ module DataMapper
2
+ module Paginator
3
+ module ControlHelper
4
+ class All
5
+ include DataMapper::Paginator::ControlHelperAbstract
6
+
7
+ attr_reader :paginator, :options
8
+
9
+ def initialize paginator, options = {}
10
+ if !paginator.is_a?( Main )
11
+ raise ArgumentError, "paginator argument is not an instance of Main"
12
+ end
13
+
14
+ @paginator = paginator
15
+ @options = options
16
+ end
17
+
18
+ def pages page_range = nil
19
+ return unless paginator.page_count > 0
20
+ return pages_in_range 1, paginator.count
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,48 @@
1
+ module DataMapper
2
+ module Paginator
3
+ module ControlHelperAbstract
4
+ ##
5
+ # Get pages using a pagination style.
6
+ #
7
+ def pages page_range = nil
8
+ raise NotImplementedError, "draw method not implemented"
9
+ end
10
+
11
+ ##
12
+ # Return pages in range.
13
+ #
14
+ # @param [Integer] lower
15
+ # @param [Integer] upper
16
+ # @return [Array]
17
+ def pages_in_range lower, upper
18
+ lower = normalize_page_number lower
19
+ upper = normalize_page_number upper
20
+
21
+ pages = []
22
+ ( lower ).upto( upper ) do | page_number |
23
+ pages.push( page_number )
24
+ end
25
+
26
+ pages
27
+ end
28
+
29
+ ##
30
+ # Normalize page number, brings the page number in range of the
31
+ # paginator.
32
+ #
33
+ # @param [Integer] page_number
34
+ # @return [Integer]
35
+ def normalize_page_number page_number
36
+ if page_number.to_i < 1
37
+ page_number = 1
38
+ end
39
+
40
+ if paginator.count > 0 && page_number > paginator.count
41
+ page_number = paginator.count
42
+ end
43
+
44
+ page_number.to_i
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,38 @@
1
+ module DataMapper
2
+ module Paginator
3
+ module ControlHelper
4
+ class Elastic < Sliding
5
+ include DataMapper::Paginator::ControlHelperAbstract
6
+
7
+ attr_reader :paginator, :options
8
+
9
+ def initialize paginator, options = {}
10
+ if !paginator.is_a?( Main )
11
+ raise ArgumentError, "paginator argument is not an instance of Main"
12
+ end
13
+
14
+ @paginator = paginator
15
+ @options = options
16
+ @options[:page_range] = options[:page_range].to_i || DataMapper::Paginator::default[:page_range]
17
+ end
18
+
19
+ def pages page_range = nil
20
+ return unless paginator.page_count > 0
21
+
22
+ page_range = options[:page_range] || page_range
23
+ page_number = normalize_page_number paginator.page
24
+ original_page_range = page_range
25
+ page_range = page_range * 2 - 1
26
+
27
+ if original_page_range + page_number - 1 < page_range
28
+ page_range = original_page_range + page_number -1
29
+ elsif original_page_range + page_number - 1 > paginator.count
30
+ page_range = original_page_range + paginator.count - page_number
31
+ end
32
+
33
+ return super( page_range )
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,40 @@
1
+ module DataMapper
2
+ module Paginator
3
+ module ControlHelper
4
+ class Jumping
5
+ include DataMapper::Paginator::ControlHelperAbstract
6
+
7
+ attr_reader :paginator, :options
8
+
9
+ def initialize paginator, options = {}
10
+ if !paginator.is_a?( Main )
11
+ raise ArgumentError, "paginator argument is not an instance of Main"
12
+ end
13
+
14
+ @paginator = paginator
15
+ @options = options
16
+ @options[:page_range] = options[:page_range].to_i || DataMapper::Paginator::default[:page_range]
17
+ end
18
+
19
+ def pages page_range = nil
20
+ return unless paginator.page_count > 0
21
+
22
+ page_range = options[:page_range] || page_range
23
+ page_number = paginator.page
24
+
25
+ delta = page_number % page_range
26
+
27
+ if delta == 0
28
+ delta = page_range
29
+ end
30
+
31
+ offset = page_number - delta
32
+ lower = offset + 1
33
+ upper = offset + page_range
34
+
35
+ return pages_in_range lower, upper
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,48 @@
1
+ module DataMapper
2
+ module Paginator
3
+ module ControlHelper
4
+ class Sliding
5
+ include DataMapper::Paginator::ControlHelperAbstract
6
+
7
+ attr_reader :paginator, :options
8
+
9
+ def initialize paginator, options = {}
10
+ if !paginator.is_a?( Main )
11
+ raise ArgumentError, "paginator argument is not an instance of Main"
12
+ end
13
+
14
+ @paginator = paginator
15
+ @options = options
16
+ @options[:page_range] = options[:page_range].to_i || DataMapper::Paginator::default[:page_range]
17
+ end
18
+
19
+ def pages page_range = nil
20
+ return unless paginator.page_count > 0
21
+
22
+ page_range = options[:page_range] || page_range
23
+
24
+ if page_range > paginator.count
25
+ page_range = paginator.count
26
+ end
27
+
28
+ delta = ( page_range / 2 ).ceil
29
+
30
+ if paginator.page - delta > paginator.count - page_range
31
+ lower = paginator.count - page_range + 1
32
+ upper = paginator.count
33
+ else
34
+ if paginator.page - delta < 0
35
+ delta = paginator.page
36
+ end
37
+
38
+ offset = paginator.page - delta
39
+ lower = offeset + 1
40
+ upper = offset + page_range
41
+ end
42
+
43
+ return pages_in_range lower, upper
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,14 @@
1
+ module DataMapper
2
+ module Paginator
3
+ @default = {
4
+ :page => 1,
5
+ :limit => 10,
6
+ :order => :id.desc,
7
+ :page_range => 10,
8
+ }
9
+
10
+ def self.default
11
+ @default
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,61 @@
1
+ module DataMapper
2
+ module Paginator
3
+ ##
4
+ # Main class, this object handle pagination attributes.
5
+ #
6
+ class Main
7
+ attr_reader :count, :page, :limit, :offset, :page_count, :next_page,
8
+ :previous_page
9
+
10
+ def initialize options = {}
11
+ @count = options[:count].to_i
12
+ @page = options[:page].to_i
13
+ @limit = options[:limit].to_i
14
+ @offset = options[:offset].to_i
15
+ @page_count = calculate_page_count
16
+ @next_page = page.to_i + 1 unless page.to_i + 1 >= page_count
17
+ @previous_page = page.to_i - 1 unless page.to_i - 1 <= 1
18
+ end
19
+
20
+ ##
21
+ # Draw pagination controls using a partial (whatever erb file).
22
+ #
23
+ # @param [String] kind
24
+ # @param [String] erb
25
+ # @param [Hash] options
26
+ # @return [String]
27
+ def to_html kind, erb, options = {}
28
+ if !File.file?( erb )
29
+ raise IOError, "erb files doesn't exists"
30
+ end
31
+
32
+ template = ERB.new File.read( erb ), 0, "%<>"
33
+
34
+ control = DataMapper::Paginator::Control.factory self, kind.to_s, options
35
+ @pages = control.pages
36
+ template.result binding
37
+ end
38
+
39
+ ##
40
+ # Get pages range using a pagination control style.
41
+ #
42
+ # @param [String] kind
43
+ #
44
+ def pages kind, options = {}
45
+ control = DataMapper::Paginator::Control.factory self, kind.to_s, options
46
+ control.pages
47
+ end
48
+
49
+ private
50
+
51
+ ##
52
+ # Calculate how many page.
53
+ #
54
+ # @return [Integer]
55
+ def calculate_page_count
56
+ @page_count = count.to_i / limit.to_i
57
+ @page_count.ceil
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,60 @@
1
+ module DataMapper
2
+ module Paginator
3
+ attr_accessor :paginator
4
+
5
+ ##
6
+ # Limit results.
7
+ #
8
+ # @param [Hash] options
9
+ # @return [Collection]
10
+ def limit options = {}
11
+ # Remove this key if we come from limit_page method.
12
+ page = options.delete :page
13
+ query = options.dup
14
+ collection = new_collection scoped_query( options = {
15
+ :limit => options[:limit],
16
+ :offset => options[:offset],
17
+ :order => [options[:order]]
18
+ }.merge( query ) )
19
+ options.merge! :count => calculate_total_records( query ), :page => page
20
+ collection.paginator = DataMapper::Paginator::Main.new options
21
+ collection
22
+ end
23
+
24
+ ##
25
+ # Limit results by page.
26
+ #
27
+ # @param [Integer, Hash] page
28
+ # @param [Hash] options
29
+ # @return [Collection]
30
+ def limit_page page = nil, options = {}
31
+ if page.is_a?( Hash )
32
+ options = page
33
+ else
34
+ options[:page] = page.to_i
35
+ end
36
+
37
+ options[:page] = options[:page].to_i > 0 ? options[:page] : DataMapper::Paginator.default[:page]
38
+ options[:limit] = options[:limit].to_i || DataMapper::Paginator.default[:limit]
39
+ options[:offset] = options[:limit] * ( options[:page] - 1 )
40
+ options[:order] = options[:order] || DataMapper::Paginator.default[:order]
41
+ limit options
42
+ end
43
+
44
+ private
45
+
46
+ ##
47
+ # Calculate total records
48
+ #
49
+ # @param [Hash] query
50
+ # @return [Integer]
51
+ def calculate_total_records query
52
+ # Remove those keys from the query
53
+ query.delete :page
54
+ query.delete :limit
55
+ query.delete :offset
56
+ collection = new_collection scoped_query( query )
57
+ collection.count.to_i
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,5 @@
1
+ module DataMapper
2
+ module Paginator
3
+ VERSION = "0.2.0"
4
+ end
5
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,10 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'shoulda'
4
+
5
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
6
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
7
+ require 'dm-paginator'
8
+
9
+ class Test::Unit::TestCase
10
+ end
@@ -0,0 +1,7 @@
1
+ require 'helper'
2
+
3
+ class TestDmPaginator < Test::Unit::TestCase
4
+ should "probably rename this file and start testing for real" do
5
+ flunk "hey buddy, you should probably rename this file and start testing for real"
6
+ end
7
+ end
metadata ADDED
@@ -0,0 +1,90 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dm-paginator
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 2
8
+ - 0
9
+ version: 0.2.0
10
+ platform: ruby
11
+ authors:
12
+ - Juan Felipe Alvarez Saldarriaga
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-03-16 00:00:00 -05:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: dm-core
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 0
29
+ - 10
30
+ - 1
31
+ version: 0.10.1
32
+ type: :development
33
+ version_requirements: *id001
34
+ description: Simple DataMapper paginator
35
+ email: nebiros@gmail.com
36
+ executables: []
37
+
38
+ extensions: []
39
+
40
+ extra_rdoc_files:
41
+ - LICENSE
42
+ - README.rdoc
43
+ files:
44
+ - lib/dm-paginator.rb
45
+ - lib/dm-paginator/control.rb
46
+ - lib/dm-paginator/control/all.rb
47
+ - lib/dm-paginator/control/control_helper_abstract.rb
48
+ - lib/dm-paginator/control/elastic.rb
49
+ - lib/dm-paginator/control/jumping.rb
50
+ - lib/dm-paginator/control/sliding.rb
51
+ - lib/dm-paginator/default.rb
52
+ - lib/dm-paginator/main.rb
53
+ - lib/dm-paginator/paginator.rb
54
+ - lib/dm-paginator/version.rb
55
+ - LICENSE
56
+ - README.rdoc
57
+ has_rdoc: true
58
+ homepage: http://github.com/nebiros/dm-paginator
59
+ licenses: []
60
+
61
+ post_install_message:
62
+ rdoc_options:
63
+ - --charset=UTF-8
64
+ require_paths:
65
+ - lib
66
+ required_ruby_version: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ segments:
71
+ - 0
72
+ version: "0"
73
+ required_rubygems_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ segments:
78
+ - 0
79
+ version: "0"
80
+ requirements: []
81
+
82
+ rubyforge_project:
83
+ rubygems_version: 1.3.6
84
+ signing_key:
85
+ specification_version: 3
86
+ summary: A simple DataMapper paginator
87
+ test_files:
88
+ - test/helper.rb
89
+ - test/test_dm-paginator.rb
90
+ - examples/paginator.rb