leaflet 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.md ADDED
@@ -0,0 +1,37 @@
1
+ # Leaflet
2
+
3
+ A very robust light-weight paginator based on [leaf](http://github.com/c7/leaf) which is based on [will_paginate](http://github.com/mislav/will_paginate).
4
+
5
+ # Design principles
6
+
7
+ * Does not fiddle with Array, ActiveRecord, or anything else. It is self-contained.
8
+ * Compatible with both [will_paginate](http://github.com/mislav/will_paginate) and [kaminari](http://github.com/amatsuda/kaminari) API.
9
+ * Never raise an exception! Negative pages will simple become positive, out of bounds simple means to the last page, etc...
10
+
11
+ # Features
12
+
13
+ * Convert an Array into a Collection
14
+ * Create a partial Collection from any data subset (something [like this](http://wiseleyb.tumblr.com/post/2896145167/willpaginate-with-redis-on-rails-3))
15
+ * Export as JSON for transferring the collection over an API
16
+
17
+ # Installation
18
+
19
+ ```ruby
20
+ gem install leaflet
21
+ ```
22
+
23
+ # Examples
24
+
25
+ ```ruby
26
+ # Converting an Array into a paginatable Collection
27
+ complete_collection = Leafet::Collection.new my_array
28
+ complete_collection.paginate(page: 5, per_page: 3) # <-- Returns an Array with the paginated subset of the original Array
29
+
30
+ # Creating a custom Collection
31
+ my_array_subset = [:d, :e, :f] # E.g. fetched from Redis according to page and per_page
32
+ collection = Leafet::Collection.new my_array_subset, total: 26, page:2, per_page: 3
33
+ ```
34
+
35
+ # Credits
36
+
37
+ Leaflet is based on [leaf](http://github.com/c7/leaf) (by Peter Hellberg) which is based on [will_paginate](http://github.com/mislav/will_paginate) by PJ Hyett, who later handed over development to Mislav Marohnić.
@@ -0,0 +1,124 @@
1
+ require 'leaflet/configuration'
2
+
3
+ module Leaflet
4
+ class Collection < Array
5
+
6
+ PartialCollectionCannotBePaginated = Class.new(StandardError)
7
+
8
+ # ––––––––––––––
9
+ # Initialization
10
+ # ––––––––––––––
11
+
12
+ def initialize(*args)
13
+ if args.size == 1
14
+ # An Array was passed in. "Convert" it to a Collection.
15
+ replace args.shift
16
+
17
+ elsif args.size == 2
18
+ # Someone is building a custom Paginator, let's fetch the data.
19
+ options = args.pop
20
+ records = Array(args.shift)
21
+ replace records
22
+ @current_page = options[:page]
23
+ @per_page = options[:per_page]
24
+ @total_entries = options[:total] || self.size
25
+
26
+ else
27
+ raise ArgumentError
28
+ end
29
+ end
30
+
31
+ def paginate(options = {})
32
+ raise PartialCollectionCannotBePaginated unless complete?
33
+ preliminary = self.class.new [], options.merge!(total: self.size)
34
+ result = self.class.new self[preliminary.offset, preliminary.per_page].to_a, options
35
+ end
36
+
37
+ # –––––––––––––––––––––––
38
+ # Public Instance Getters
39
+ # –––––––––––––––––––––––
40
+
41
+ def total_entries
42
+ Leaflet.positify {
43
+ @total_entries ||= self.size
44
+ }
45
+ end
46
+ alias :total_count :total_entries # Kaminari
47
+
48
+ def per_page
49
+ Leaflet.positify(max: Leaflet.config.max_per_page) {
50
+ @per_page ||= Leaflet.config.default_per_page
51
+ }
52
+ end
53
+ alias :limit_value :per_page # Kaminari
54
+
55
+ def current_page
56
+ Leaflet.positify(max: total_pages) {
57
+ @current_page ||= 1
58
+ }
59
+ end
60
+
61
+ # ––––––––––––––––––––
62
+ # Public Class Getters
63
+ # ––––––––––––––––––––
64
+
65
+ def offset
66
+ (current_page - 1) * per_page
67
+ end
68
+ alias :offset_value :offset # Kaminari
69
+
70
+ def total_pages
71
+ Leaflet.positify {
72
+ total_entries.zero? ? 1 : (total_entries / per_page.to_f).ceil
73
+ }
74
+ end
75
+
76
+ def inspect
77
+ result = ['#<Collection with']
78
+ result << (complete? ? "#{self.size} records" : "#{self.size}/#{total_entries} records")
79
+ result << "on page #{current_page}/#{total_pages} (#{per_page} per page): #{self.to_a}>"
80
+ result.join(' ')
81
+ end
82
+
83
+ def previous_page
84
+ current_page > 1 ? (current_page - 1) : nil
85
+ end
86
+
87
+ def next_page
88
+ current_page < total_pages ? (current_page + 1) : nil
89
+ end
90
+
91
+ def first_page?
92
+ current_page == 1
93
+ end
94
+
95
+ def last_page?
96
+ current_page == total_pages
97
+ end
98
+
99
+ def as_json(options = {})
100
+ {
101
+ total_entries: total_entries,
102
+ total_count: total_count,
103
+ per_page: per_page,
104
+ limit_value: limit_value,
105
+ current_page: current_page,
106
+ offset: offset,
107
+ offset_value: offset_value,
108
+ otal_pages: total_pages,
109
+ records: self.to_a
110
+ }
111
+ end
112
+
113
+ private
114
+
115
+ # ––––––––––––––––––––––
116
+ # Internal Class Getters
117
+ # ––––––––––––––––––––––
118
+
119
+ def complete?
120
+ self.size == total_entries
121
+ end
122
+
123
+ end
124
+ end
@@ -0,0 +1,42 @@
1
+ require 'logger'
2
+
3
+ module Leaflet
4
+ class Configuration
5
+
6
+ attr_writer :default_per_page, :max_per_page
7
+
8
+ def default_per_page
9
+ Leaflet.positify {
10
+ @default_per_page ||= 20
11
+ }
12
+ end
13
+
14
+ def max_per_page
15
+ Leaflet.positify {
16
+ @max_per_page ||= 30
17
+ }
18
+ end
19
+
20
+ end
21
+ end
22
+
23
+ module Leaflet
24
+
25
+ # Public: Returns the the configuration instance.
26
+ #
27
+ def self.config
28
+ @config ||= Configuration.new
29
+ end
30
+
31
+ # Public: Yields the configuration instance.
32
+ #
33
+ def self.configure(&block)
34
+ yield config
35
+ end
36
+
37
+ # Public: Reset the configuration (useful for testing)
38
+ #
39
+ def self.reset!
40
+ @config = nil
41
+ end
42
+ end
@@ -0,0 +1,9 @@
1
+ module Leaflet
2
+ module VERSION
3
+ MAJOR = 0
4
+ MINOR = 0
5
+ TINY = 1
6
+
7
+ STRING = [MAJOR, MINOR, TINY].join('.')
8
+ end
9
+ end
data/lib/leaflet.rb ADDED
@@ -0,0 +1,35 @@
1
+ require 'leaflet/configuration'
2
+ require 'leaflet/collection'
3
+ require 'leaflet/version'
4
+
5
+ module Leaflet
6
+
7
+ def self.positify(*args, &block)
8
+ if block_given?
9
+ raise(ArgumentError, "You can only pass in one options Hash in block mode, not #{args.inspect}") if args.size > 1
10
+ object = block.call
11
+ options = args.shift || {}
12
+ else
13
+ case args.size
14
+ when 1
15
+ object = args.shift
16
+ options = {}
17
+ raise(ArgumentError, "You forgot the brackets in your call. Try: Leaflet.positify(...) do") if object.is_a?(Hash)
18
+ when 2
19
+ object = args.shift
20
+ options = args.shift
21
+ else
22
+ raise ArgumentError, "You must pass in an object and may pass in an options Hash, not #{args.inspect}"
23
+ end
24
+ end
25
+
26
+ options[:max] = positify(options[:max]) if options[:max]
27
+
28
+ return 1 unless object.respond_to?(:to_i)
29
+ result = object.to_i.abs > 0 ? object.to_i.abs : 1
30
+ result = options[:max] if options[:max] && options[:max] < result
31
+ result
32
+ end
33
+
34
+ end
35
+
@@ -0,0 +1,97 @@
1
+ require 'spec_helper'
2
+
3
+ describe Leaflet::Collection do
4
+ let(:array) { ('a'..'e').to_a }
5
+
6
+ context 'converting an Array into a Collection' do
7
+ let(:collection) { Leaflet::Collection.new(array) }
8
+
9
+ describe '#current_page' do
10
+ it 'is the passed in parameter' do
11
+ collection.current_page.should == 1
12
+ end
13
+
14
+ it 'never gets out of bounds' do
15
+ collection = Leaflet::Collection.new(array, page: 99, per_page: 2)
16
+ collection.current_page.should == 3
17
+ end
18
+ end
19
+
20
+ describe '#per_page' do
21
+ it 'is the default per_page' do
22
+ collection.per_page.should == 20
23
+ end
24
+ end
25
+
26
+ describe '#limit_value ' do
27
+ it 'is an alias for per_page' do
28
+ collection.per_page.should == collection.per_page
29
+ end
30
+ end
31
+
32
+ describe '#total_entries' do
33
+ it 'corresponds to the records size' do
34
+ collection.total_entries.should == 5
35
+ end
36
+ end
37
+
38
+ describe '#total_count' do
39
+ it 'is an alias for #total_entries' do
40
+ collection.total_count.should == collection.total_entries
41
+ end
42
+ end
43
+
44
+ describe '#paginate' do
45
+ it 'returns a subset of original collection' do
46
+ collection.paginate(page: 1, per_page: 3).should == %w{ a b c }
47
+ end
48
+
49
+ it 'can be shorter than per_page if on last page' do
50
+ collection.paginate(page: 2, per_page: 3).should == %w{ d e }
51
+ end
52
+
53
+ it 'includes whole collection if per_page permits' do
54
+ collection.paginate(page: 1, per_page: 5).should == collection
55
+ end
56
+
57
+ it 'never gets out of bounds' do
58
+ collection.paginate(page: 4, per_page: 2).should == %w{ e }
59
+ end
60
+ end
61
+ end
62
+
63
+ context 'custom Collection' do
64
+ let(:collection) { Leaflet::Collection.new(array, total: 40, per_page: 4, page: 4) }
65
+
66
+ describe '#total_entries' do
67
+ it 'is the passed in parameter' do
68
+ collection.total_entries.should == 40
69
+ end
70
+ end
71
+
72
+ describe '#total_pages' do
73
+ it 'is calculated from the passed in total' do
74
+ collection.total_pages.should == 10
75
+ end
76
+ end
77
+
78
+ describe '#per_page' do
79
+ it 'is calculated from the passed in total' do
80
+ collection.per_page.should == 4
81
+ end
82
+ end
83
+
84
+ describe '#current_page' do
85
+ it 'is the passed in parameter' do
86
+ collection.current_page.should == 4
87
+ end
88
+ end
89
+
90
+ describe '#paginate' do
91
+ it 'is not possible on a non-complete collection' do
92
+ expect { collection.paginate }.to raise_exception(Leaflet::Collection::PartialCollectionCannotBePaginated)
93
+ end
94
+ end
95
+ end
96
+
97
+ end
@@ -0,0 +1,45 @@
1
+ require 'spec_helper'
2
+
3
+ describe Leaflet do
4
+
5
+ describe '.positify' do
6
+ it 'makes negative numbers positive' do
7
+ Leaflet.positify(-5).should == 5
8
+ end
9
+
10
+ it 'turns 0 to 1' do
11
+ Leaflet.positify(0).should == 1
12
+ end
13
+
14
+ it 'returns 1 on non Fixnumerable objects' do
15
+ Leaflet.positify(OpenStruct.new).should == 1
16
+ end
17
+
18
+ it 'chops Floats to Fixnums' do
19
+ Leaflet.positify(5.9).should == 5
20
+ end
21
+
22
+ it 'sets a ceiling' do
23
+ Leaflet.positify(30, max: 22).should == 22
24
+ end
25
+
26
+ it 'ignores the ceiling if the value is below it ' do
27
+ Leaflet.positify(30, max: 35).should == 30
28
+ end
29
+
30
+ context 'block mode' do
31
+ it 'makes negative numbers positive' do
32
+ Leaflet.positify { -5 }.should == 5
33
+ end
34
+
35
+ it 'sets a ceiling' do
36
+ Leaflet.positify(max: 25) { 30 }.should == 25
37
+ end
38
+
39
+ it 'ignores the ceiling if the value is below it ' do
40
+ Leaflet.positify(max: 35) { 30 }.should == 30
41
+ end
42
+ end
43
+ end
44
+
45
+ end
@@ -0,0 +1 @@
1
+ require 'leaflet'
metadata ADDED
@@ -0,0 +1,104 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: leaflet
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - bukowskis
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-04-05 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: guard-rspec
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rb-fsevent
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ description: A very robust, custom, light-weight paginator. Based on the leaf gem
63
+ which is based on the will_paginate gem.
64
+ email:
65
+ executables: []
66
+ extensions: []
67
+ extra_rdoc_files: []
68
+ files:
69
+ - lib/leaflet/collection.rb
70
+ - lib/leaflet/configuration.rb
71
+ - lib/leaflet/version.rb
72
+ - lib/leaflet.rb
73
+ - spec/lib/leaflet/collection_spec.rb
74
+ - spec/lib/leaflet_spec.rb
75
+ - spec/spec_helper.rb
76
+ - README.md
77
+ homepage: https://github.com/bukowskis/leaflet
78
+ licenses:
79
+ - MIT
80
+ post_install_message:
81
+ rdoc_options:
82
+ - --encoding
83
+ - UTF-8
84
+ require_paths:
85
+ - lib
86
+ required_ruby_version: !ruby/object:Gem::Requirement
87
+ none: false
88
+ requirements:
89
+ - - ! '>='
90
+ - !ruby/object:Gem::Version
91
+ version: '0'
92
+ required_rubygems_version: !ruby/object:Gem::Requirement
93
+ none: false
94
+ requirements:
95
+ - - ! '>='
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ requirements: []
99
+ rubyforge_project:
100
+ rubygems_version: 1.8.23
101
+ signing_key:
102
+ specification_version: 3
103
+ summary: A very robust, custom, light-weight paginator.
104
+ test_files: []