kaminari-logarithmic 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 962826fa842b45f3e37e5b61296f16f8baab560b
4
+ data.tar.gz: e9a3d9f8e9539b84526056acffa3af1fbc17a449
5
+ SHA512:
6
+ metadata.gz: ef7496175482093639ed57a59dbba40178117fd01bade464fb331f5d2ec08ecc0d0c2459a6f9795e2569e1bbf6c6effc088d7b3de8ed45adbef415c903f3a050
7
+ data.tar.gz: fd33a556b2819a0fca4a6c81def08b4a944029dc87648d4ff483ad69c8543f4ebd56a6d4688d29ae8db7bc530b1a4fce1e67d8ab9910b54ff04a165eaceb6da2
data/.gitignore ADDED
@@ -0,0 +1,15 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
15
+ *.DS_Store
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format=d
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in kaminari-logarithmic.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Anton Lee
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,44 @@
1
+ # Kaminari::Logarithmic
2
+
3
+ This plugin extends popular [kaminari](https://github.com/amatsuda/kaminari) gem to provide functionality for distributing big number of pages logarithmically. Such approach originally was discussed [here](http://stackoverflow.com/questions/7835752/how-to-do-page-navigation-for-many-many-pages-logarithmic-page-navigation).
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'kaminari-logarithmic'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install kaminari-logarithmic
20
+
21
+ ## Usage
22
+
23
+ Do all the pagination stuff in controller and model usually. In your view use special helper instead of `paginate`:
24
+
25
+ ```ruby
26
+ paginate_logarithmic @your_collection
27
+ ```
28
+ By default even distribution strategy is used. You can specify strategy with `strategy` option:
29
+
30
+ ```ruby
31
+ paginate_logarithmic @users, strategy: :fixed_steps
32
+ ```
33
+ At the moment 2 strategies are available(TODO: describe both):
34
+
35
+ 1. `:even`.
36
+ 2. `:fixed_steps`
37
+
38
+ ## Contributing
39
+
40
+ 1. Fork it ( https://github.com/[my-github-username]/kaminari-logarithmic/fork )
41
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
42
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
43
+ 4. Push to the branch (`git push origin my-new-feature`)
44
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'kaminari/logarithmic/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "kaminari-logarithmic"
8
+ spec.version = Kaminari::Logarithmic::VERSION
9
+ spec.authors = ["Anton Lee"]
10
+ spec.email = ["antoshalee@gmail.com"]
11
+ spec.summary = %q{Kaminari extension for logarithmic pagination}
12
+ spec.description = %q{Kaminari extension for logarithmic pagination}
13
+ spec.homepage = "https://github.com/antoshalee/kaminari-logarithmic"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "kaminari"
22
+
23
+ spec.add_development_dependency "bundler", "~> 1.7"
24
+ spec.add_development_dependency "rake", "~> 10.0"
25
+ spec.add_development_dependency "rspec"
26
+ end
@@ -0,0 +1,10 @@
1
+ module Kaminari
2
+ module Logarithmic
3
+ module ActionViewExtension
4
+ def paginate_logarithmic(scope, options = {}, &block)
5
+ paginator = Kaminari::Logarithmic::Paginator.new self, options.reverse_merge(:current_page => scope.current_page, :total_pages => scope.total_pages, :per_page => scope.limit_value, :remote => false)
6
+ paginator.to_s
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,9 @@
1
+ module Kaminari
2
+ module Logarithmic
3
+ module PageProxyExtension
4
+ def logaritmic_page?
5
+ @options[:logarithmic_pages].include? @page
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,53 @@
1
+ module Kaminari
2
+ module Logarithmic
3
+ class Paginator < ::Kaminari::Helpers::Paginator
4
+ def initialize(template, options)
5
+ @logarithmic_strategy = options[:strategy]
6
+ super(template, options)
7
+
8
+ precalculate_logarithnmic_pages
9
+ end
10
+
11
+ def each_relevant_page
12
+ extended_options = @window_options.merge(
13
+ logarithmic_pages: @left_log_seq + @right_log_seq
14
+ )
15
+
16
+ return to_enum(:each_relevant_page) unless block_given?
17
+ relevant_pages(@window_options).each do |i|
18
+ yield PageProxy.new(extended_options, i, @last)
19
+ end
20
+ end
21
+
22
+ alias each_page each_relevant_page
23
+
24
+ def relevant_pages(options)
25
+ left_window_plus_one = 1.upto(options[:left] + 1).to_a
26
+ right_window_plus_one = (options[:total_pages] - options[:right]).upto(options[:total_pages]).to_a
27
+ inside_window_plus_each_sides = (options[:current_page] - options[:window] - 1).upto(options[:current_page] + options[:window] + 1).to_a
28
+
29
+ log_pages_with_gaps = \
30
+ @left_log_seq.map { |p| [p, p - 1] }.flatten +
31
+ @right_log_seq.map { |p| [p, p + 1] }.flatten
32
+
33
+ (
34
+ left_window_plus_one +
35
+ inside_window_plus_each_sides +
36
+ log_pages_with_gaps +
37
+ right_window_plus_one
38
+ ).uniq.sort.reject { |x| (x < 1) || (x > options[:total_pages]) }
39
+ end
40
+
41
+ def precalculate_logarithnmic_pages
42
+ builder_options = { strategy: @logarithmic_strategy }
43
+ left_start = @window_options[:current_page] - @window_options[:window] - 1
44
+ left_finish = @window_options[:left] + 1
45
+ @left_log_seq = SeqBuilder.new(left_start, left_finish, builder_options).build.reverse
46
+
47
+ right_start = @window_options[:current_page] + @window_options[:window] + 1
48
+ right_finish = @window_options[:total_pages] - @window_options[:right]
49
+ @right_log_seq = SeqBuilder.new(right_start, right_finish, builder_options).build
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,24 @@
1
+ module Kaminari
2
+ module Logarithmic
3
+ class SeqBuilder
4
+ DEFAULT_STRATEGY = :even
5
+
6
+ def initialize(start, finish, options = {})
7
+ @options = options
8
+ build_strategy(start, finish)
9
+ end
10
+
11
+ def build
12
+ @strategy.build
13
+ end
14
+
15
+ private
16
+
17
+ def build_strategy(start, finish)
18
+ code = @options[:strategy] || DEFAULT_STRATEGY
19
+ klass = "Kaminari::Logarithmic::Strategies::#{code.to_s.camelize}Strategy".constantize
20
+ @strategy = klass.new(start, finish)
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,29 @@
1
+ module Kaminari
2
+ module Logarithmic
3
+ module Strategies
4
+ class BaseStrategy
5
+ def build
6
+ fail NotImplementedError
7
+ end
8
+
9
+ private
10
+
11
+ def asc?
12
+ @asc ||= (@global_start <= @global_finish)
13
+ end
14
+
15
+ def desc?
16
+ !asc?
17
+ end
18
+
19
+ def enough?(value)
20
+ if asc?
21
+ value < @global_finish
22
+ else
23
+ value > @global_finish
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,29 @@
1
+ module Kaminari
2
+ module Logarithmic
3
+ module Strategies
4
+ class EvenStrategy < BaseStrategy
5
+ def initialize(start, finish, base = 2)
6
+ @global_start = start
7
+ @global_finish = finish
8
+ @base = base
9
+ end
10
+
11
+ def build
12
+ value = @global_start
13
+ step = @base
14
+ result = []
15
+ while enough?(value)
16
+ result << value
17
+ if asc?
18
+ value = value + step
19
+ else
20
+ value = value - step
21
+ end
22
+ step *= @base
23
+ end
24
+ result
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,64 @@
1
+ module Kaminari
2
+ module Logarithmic
3
+ module Strategies
4
+ class FixedStepsStrategy < BaseStrategy
5
+ def initialize(start, finish, base = 10)
6
+ @global_start = start
7
+ @global_finish = finish
8
+ @base = base
9
+ end
10
+
11
+ def build
12
+ start = next_point_or_itself(@global_start, @base)
13
+ step = @base
14
+ result = []
15
+ while enough?(start)
16
+ finish = next_finish(start, step)
17
+ result += seq_with_step(start, finish, step)
18
+ start = next_point(finish, step * @base)
19
+ step *= @base
20
+ end
21
+ result
22
+ end
23
+
24
+ private
25
+
26
+ def enough?(value)
27
+ if asc?
28
+ value < @global_finish
29
+ else
30
+ value > @global_finish
31
+ end
32
+ end
33
+
34
+ def next_finish(start, step)
35
+ variants = [@global_finish, next_point(start, step * @base)]
36
+ asc? ? variants.min : variants.max
37
+ end
38
+
39
+ # if value is divisible by step return itself
40
+ def next_point_or_itself(value, step)
41
+ if (value % step) == 0
42
+ value
43
+ else
44
+ next_point(value, step)
45
+ end
46
+ end
47
+
48
+ def next_point(value, step)
49
+ if asc?
50
+ ((value + step) / step) * step
51
+ else
52
+ return (value - step) if value % step == 0
53
+ (value / step) * step
54
+ end
55
+ end
56
+
57
+ def seq_with_step(start, finish, step)
58
+ step = -step if desc?
59
+ start.step(finish, step).to_a
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,5 @@
1
+ module Kaminari
2
+ module Logarithmic
3
+ VERSION = "0.0.1"
4
+ end
5
+ end
@@ -0,0 +1,17 @@
1
+ require "kaminari"
2
+ require "kaminari/helpers/paginator"
3
+ require "kaminari/logarithmic/version"
4
+ require "kaminari/logarithmic/action_view_extension"
5
+ require "kaminari/logarithmic/page_proxy_extension"
6
+ require "kaminari/logarithmic/strategies/base_strategy"
7
+ require "kaminari/logarithmic/strategies/even_strategy"
8
+ require "kaminari/logarithmic/strategies/fixed_steps_strategy"
9
+ require "kaminari/logarithmic/seq_builder"
10
+
11
+ module Kaminari
12
+ module Logarithmic
13
+ end
14
+ end
15
+
16
+ ::ActionView::Base.send :include, Kaminari::Logarithmic::ActionViewExtension
17
+ ::Kaminari::Helpers::Paginator::PageProxy.send :include, Kaminari::Logarithmic::PageProxyExtension
@@ -0,0 +1,7 @@
1
+ require 'bundler/setup'
2
+ Bundler.setup
3
+
4
+ require 'kaminari/logarithmic'
5
+
6
+ RSpec.configure do |config|
7
+ end
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+
3
+ describe Kaminari::Logarithmic::Strategies::EvenStrategy do
4
+ describe ".build" do
5
+ {
6
+ [1, 100] => [1, 3, 7, 15, 31, 63],
7
+ [100, 1] => [100, 98, 94, 86, 70, 38]
8
+ }.each do |range, pages|
9
+ it { expect(described_class.new(*range).build).to eq pages }
10
+ end
11
+ end
12
+
13
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ describe Kaminari::Logarithmic::Strategies::FixedStepsStrategy do
4
+ describe ".build" do
5
+ {
6
+ [1, 100] => [10, 20, 30, 40, 50, 60, 70, 80, 90, 100],
7
+ [10, 100] => [10, 20, 30, 40, 50, 60, 70, 80, 90, 100],
8
+ [1, 101] => [10, 20, 30, 40, 50, 60, 70, 80, 90, 100],
9
+ [45, 670] => [50, 60, 70, 80, 90, 100, 200, 300, 400, 500, 600],
10
+ [315, 2346] => [320, 330, 340, 350, 360, 370, 380, 390, 400, 500, 600, 700, 800, 900, 1000, 2000],
11
+ [315, 22346] => [320, 330, 340, 350, 360, 370, 380, 390, 400, 500, 600, 700, 800, 900, 1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000, 10000, 20000],
12
+ [673, 45] => [670, 660, 650, 640, 630, 620, 610, 600, 500, 400, 300, 200, 100],
13
+ [100, 1] => [100, 90, 80, 70, 60, 50, 40, 30, 20, 10],
14
+ [100, 10] => [100, 90, 80, 70, 60, 50, 40, 30, 20, 10]
15
+ }.each do |range, pages|
16
+ it { expect(described_class.new(*range).build).to eq pages }
17
+ end
18
+ end
19
+
20
+ end
metadata ADDED
@@ -0,0 +1,122 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: kaminari-logarithmic
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Anton Lee
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-03-16 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: kaminari
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.7'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.7'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '10.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '10.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: Kaminari extension for logarithmic pagination
70
+ email:
71
+ - antoshalee@gmail.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - ".gitignore"
77
+ - ".rspec"
78
+ - Gemfile
79
+ - LICENSE.txt
80
+ - README.md
81
+ - Rakefile
82
+ - kaminari-logarithmic.gemspec
83
+ - lib/kaminari/logarithmic.rb
84
+ - lib/kaminari/logarithmic/action_view_extension.rb
85
+ - lib/kaminari/logarithmic/page_proxy_extension.rb
86
+ - lib/kaminari/logarithmic/paginator.rb
87
+ - lib/kaminari/logarithmic/seq_builder.rb
88
+ - lib/kaminari/logarithmic/strategies/base_strategy.rb
89
+ - lib/kaminari/logarithmic/strategies/even_strategy.rb
90
+ - lib/kaminari/logarithmic/strategies/fixed_steps_strategy.rb
91
+ - lib/kaminari/logarithmic/version.rb
92
+ - spec/spec_helper.rb
93
+ - spec/strategies/even_strategy_spec.rb
94
+ - spec/strategies/fixed_steps_strategy_spec.rb
95
+ homepage: https://github.com/antoshalee/kaminari-logarithmic
96
+ licenses:
97
+ - MIT
98
+ metadata: {}
99
+ post_install_message:
100
+ rdoc_options: []
101
+ require_paths:
102
+ - lib
103
+ required_ruby_version: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ required_rubygems_version: !ruby/object:Gem::Requirement
109
+ requirements:
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ version: '0'
113
+ requirements: []
114
+ rubyforge_project:
115
+ rubygems_version: 2.2.2
116
+ signing_key:
117
+ specification_version: 4
118
+ summary: Kaminari extension for logarithmic pagination
119
+ test_files:
120
+ - spec/spec_helper.rb
121
+ - spec/strategies/even_strategy_spec.rb
122
+ - spec/strategies/fixed_steps_strategy_spec.rb