dm-paginator 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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