kaminari 0.1.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of kaminari might be problematic. Click here for more details.

@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format=d
data/Gemfile ADDED
@@ -0,0 +1,21 @@
1
+ source 'http://rubygems.org'
2
+ # Add dependencies required to use your gem here.
3
+ # Example:
4
+ # gem "activesupport", ">= 2.3.5"
5
+
6
+ # Add dependencies to develop your gem here.
7
+ # Include everything needed to run rake, tests, features, etc.
8
+ group :development do
9
+ gem 'rspec', '>= 2.4.0'
10
+ gem 'rr', '>= 1.0.2'
11
+ gem 'bundler', '>= 1.0.0'
12
+ gem 'jeweler', '>= 1.5.2'
13
+ gem 'rcov', '>= 0'
14
+ gem 'rails', :git => 'git://github.com/rails/rails.git'
15
+ # gem 'rails', '>= 3.0.3'
16
+ gem 'rack', :git => 'git://github.com/rack/rack.git'
17
+ gem 'arel', :git => 'git://github.com/rails/arel.git'
18
+ gem 'rspec-rails', :git => 'git://github.com/rspec/rspec-rails.git'# 2.4.1 needed
19
+ gem 'sqlite3', '>= 1.3.3'
20
+ gem 'ruby-debug'
21
+ end
@@ -0,0 +1,136 @@
1
+ GIT
2
+ remote: git://github.com/rack/rack.git
3
+ revision: 1c2715778d3753dce4d8df19e3d3cc698aed20c6
4
+ specs:
5
+ rack (1.2.1)
6
+
7
+ GIT
8
+ remote: git://github.com/rails/arel.git
9
+ revision: 4d92a6b33476a5b324188bd86dfa5b5d3f4dcd3a
10
+ specs:
11
+ arel (2.0.7.beta.20110121165657)
12
+
13
+ GIT
14
+ remote: git://github.com/rails/rails.git
15
+ revision: 59f7780a3454a14054d1d33d9b6e31192ab2e58b
16
+ specs:
17
+ actionmailer (3.1.0.beta)
18
+ actionpack (= 3.1.0.beta)
19
+ mail (~> 2.2.15)
20
+ actionpack (3.1.0.beta)
21
+ activemodel (= 3.1.0.beta)
22
+ activesupport (= 3.1.0.beta)
23
+ builder (~> 3.0.0)
24
+ erubis (~> 2.6.6)
25
+ i18n (~> 0.5.0)
26
+ rack (~> 1.2.1)
27
+ rack-cache (~> 1.0.0)
28
+ rack-mount (~> 0.6.13)
29
+ rack-test (~> 0.5.7)
30
+ tzinfo (~> 0.3.23)
31
+ activemodel (3.1.0.beta)
32
+ activesupport (= 3.1.0.beta)
33
+ bcrypt-ruby (~> 2.1.4)
34
+ builder (~> 3.0.0)
35
+ i18n (~> 0.5.0)
36
+ activerecord (3.1.0.beta)
37
+ activemodel (= 3.1.0.beta)
38
+ activesupport (= 3.1.0.beta)
39
+ arel (~> 2.0.2)
40
+ tzinfo (~> 0.3.23)
41
+ activeresource (3.1.0.beta)
42
+ activemodel (= 3.1.0.beta)
43
+ activesupport (= 3.1.0.beta)
44
+ activesupport (3.1.0.beta)
45
+ rails (3.1.0.beta)
46
+ actionmailer (= 3.1.0.beta)
47
+ actionpack (= 3.1.0.beta)
48
+ activerecord (= 3.1.0.beta)
49
+ activeresource (= 3.1.0.beta)
50
+ activesupport (= 3.1.0.beta)
51
+ bundler (~> 1.0)
52
+ railties (= 3.1.0.beta)
53
+ railties (3.1.0.beta)
54
+ actionpack (= 3.1.0.beta)
55
+ activesupport (= 3.1.0.beta)
56
+ rake (>= 0.8.7)
57
+ thor (~> 0.14.4)
58
+
59
+ GIT
60
+ remote: git://github.com/rspec/rspec-rails.git
61
+ revision: 3b279c63397975ef95219ecdb53b497ebc8dc9f0
62
+ specs:
63
+ rspec-rails (2.4.1)
64
+ actionpack (~> 3.0)
65
+ activesupport (~> 3.0)
66
+ railties (~> 3.0)
67
+ rspec (~> 2.4.0)
68
+
69
+ GEM
70
+ remote: http://rubygems.org/
71
+ specs:
72
+ abstract (1.0.0)
73
+ bcrypt-ruby (2.1.4)
74
+ builder (3.0.0)
75
+ columnize (0.3.2)
76
+ diff-lcs (1.1.2)
77
+ erubis (2.6.6)
78
+ abstract (>= 1.0.0)
79
+ git (1.2.5)
80
+ i18n (0.5.0)
81
+ jeweler (1.5.2)
82
+ bundler (~> 1.0.0)
83
+ git (>= 1.2.5)
84
+ rake
85
+ ruby-debug
86
+ linecache (0.43)
87
+ mail (2.2.15)
88
+ activesupport (>= 2.3.6)
89
+ i18n (>= 0.4.0)
90
+ mime-types (~> 1.16)
91
+ treetop (~> 1.4.8)
92
+ mime-types (1.16)
93
+ polyglot (0.3.1)
94
+ rack-cache (1.0)
95
+ rack (>= 0.4)
96
+ rack-mount (0.6.13)
97
+ rack (>= 1.0.0)
98
+ rack-test (0.5.7)
99
+ rack (>= 1.0)
100
+ rake (0.8.7)
101
+ rcov (0.9.9)
102
+ rr (1.0.2)
103
+ rspec (2.4.0)
104
+ rspec-core (~> 2.4.0)
105
+ rspec-expectations (~> 2.4.0)
106
+ rspec-mocks (~> 2.4.0)
107
+ rspec-core (2.4.0)
108
+ rspec-expectations (2.4.0)
109
+ diff-lcs (~> 1.1.2)
110
+ rspec-mocks (2.4.0)
111
+ ruby-debug (0.10.4)
112
+ columnize (>= 0.1)
113
+ ruby-debug-base (~> 0.10.4.0)
114
+ ruby-debug-base (0.10.4)
115
+ linecache (>= 0.3)
116
+ sqlite3 (1.3.3)
117
+ thor (0.14.6)
118
+ treetop (1.4.9)
119
+ polyglot (>= 0.3.1)
120
+ tzinfo (0.3.24)
121
+
122
+ PLATFORMS
123
+ ruby
124
+
125
+ DEPENDENCIES
126
+ arel!
127
+ bundler (>= 1.0.0)
128
+ jeweler (>= 1.5.2)
129
+ rack!
130
+ rails!
131
+ rcov
132
+ rr (>= 1.0.2)
133
+ rspec (>= 2.4.0)
134
+ rspec-rails!
135
+ ruby-debug
136
+ sqlite3 (>= 1.3.3)
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Akira Matsuda
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.
@@ -0,0 +1,81 @@
1
+ = Kaminari
2
+
3
+ A Scope & Engine based clean and powerful and customizable and sophisticated paginator for Rails 3
4
+
5
+
6
+ == Features
7
+
8
+ * Clean
9
+ Does not globally pollute Array, Hash, Object or AR::Base.
10
+
11
+ * Easy to use
12
+ Just bundle the gem, then your models are ready to be paginated. No configuration. Don't have to define anything in your models or helpers.
13
+
14
+ * Scope based simple API
15
+ Everything is method chainable. No Hash for the query. You know, that's the Rails 3 way.
16
+ No special collection class or something for the paginated values but uses a general AR::Relation instance. So, of course you can chain any other conditions before or after the paginator scope.
17
+
18
+ * Engine based customizable helper
19
+ As the whole pagination helper is basically just a collection of links and non-links, Kaminari renders each of them through its own partial template inside the Engine. So, you can easily modify their behaviour or style or whatever by overriding partial templates.
20
+
21
+
22
+ == Rails versions
23
+
24
+ 3.0.x and 3.1
25
+
26
+
27
+ == Install
28
+
29
+ Put this line in your Gemfile:
30
+ gem 'kaminari'
31
+
32
+ Then bundle:
33
+ % bundle
34
+
35
+
36
+ == Usage
37
+
38
+ * Fetch the 7th page of the users (per_page = 10 by default)
39
+
40
+ @users = User.page(7)
41
+
42
+ * Show a lot more users per each page (change the per_page value)
43
+
44
+ @users = User.page(7).per(30)
45
+
46
+ * Typically, your controller code will look like this:
47
+
48
+ @users = User.page params[:page]
49
+
50
+ * In your view
51
+
52
+ <%= paginate @users %>
53
+
54
+ * Specify the "window" size
55
+
56
+ # "inner window" (4 by default)
57
+
58
+ <%= paginate @users, :window => 3 %>
59
+
60
+ # "outer window" (1 by default)
61
+
62
+ <%= paginate @users, :outer_window => 3 %>
63
+
64
+ # outer window can be separetely specified by "left", "right" (1 by default)
65
+
66
+ <%= paginate @users, :left => 0, :right => 2 %>
67
+
68
+ * Customize the pagination helper
69
+
70
+ % rails g kaminari:views
71
+ Then edit the partials in your app's app/views/kaminari/ directory.
72
+
73
+
74
+ == Contributing to Kaminari
75
+
76
+ * Fork, fix, then send me a pull request.
77
+
78
+
79
+ == Copyright
80
+
81
+ Copyright (c) 2011 Akira Matsuda. See LICENSE.txt for further details.
@@ -0,0 +1,52 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17
+ gem.name = "kaminari"
18
+ gem.homepage = "http://github.com/amatsuda/kaminari"
19
+ gem.license = "MIT"
20
+ gem.summary = 'A pagnation engine plugin for Rails 3'
21
+ gem.description = 'Kaminari is a Scope & Engine based clean and powerful and customizable and sophisticated paginator for Rails 3'
22
+ gem.email = "ronnie@dio.jp"
23
+ gem.authors = ["Akira Matsuda"]
24
+ # Include your dependencies below. Runtime dependencies are required when using your gem,
25
+ # and development dependencies are only needed for development (ie running rake tasks, tests, etc)
26
+ gem.add_runtime_dependency 'rails', '>= 3.0.0'
27
+ # gem.add_development_dependency 'rspec', '> 1.2.3'
28
+ end
29
+ Jeweler::RubygemsDotOrgTasks.new
30
+
31
+ require 'rspec/core'
32
+ require 'rspec/core/rake_task'
33
+ RSpec::Core::RakeTask.new(:spec) do |spec|
34
+ spec.pattern = FileList['spec/**/*_spec.rb']
35
+ end
36
+
37
+ RSpec::Core::RakeTask.new(:rcov) do |spec|
38
+ spec.pattern = 'spec/**/*_spec.rb'
39
+ spec.rcov = true
40
+ end
41
+
42
+ task :default => :spec
43
+
44
+ require 'rake/rdoctask'
45
+ Rake::RDocTask.new do |rdoc|
46
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
47
+
48
+ rdoc.rdoc_dir = 'rdoc'
49
+ rdoc.title = "kaminari #{version}"
50
+ rdoc.rdoc_files.include('README*')
51
+ rdoc.rdoc_files.include('lib/**/*.rb')
52
+ end
@@ -0,0 +1,11 @@
1
+ * partialize the outer div
2
+
3
+ * suppress logging when rendering each partial
4
+
5
+ * add generator option to copy particular template
6
+
7
+ * add Haml generator
8
+
9
+ * add Ajax generator
10
+
11
+ * I18n?
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1 @@
1
+ <span class="page current"><%= page %></span>
@@ -0,0 +1,3 @@
1
+ <span class="page first">
2
+ <%= link_to page, page_url %>
3
+ </span>
@@ -0,0 +1,3 @@
1
+ <span class="page last">
2
+ <%= link_to page, page_url %>
3
+ </span>
@@ -0,0 +1,3 @@
1
+ <span class="next">
2
+ <%= link_to_if (current_page < num_pages), raw('Next &raquo;'), next_url, :class => 'next', :rel => 'next' %>
3
+ </span>
@@ -0,0 +1 @@
1
+ <span class="next"></span>
@@ -0,0 +1,3 @@
1
+ <span class="page">
2
+ <%= link_to page, page_url %>
3
+ </span>
@@ -0,0 +1,3 @@
1
+ <span class="prev">
2
+ <%= link_to_if (current_page > 1), raw('&laquo; Prev'), prev_url, :class => 'prev', :rel => 'prev' %>
3
+ </span>
@@ -0,0 +1 @@
1
+ <span class="prev"></span>
@@ -0,0 +1 @@
1
+ <span class="page">...</span>
@@ -0,0 +1,113 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{kaminari}
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Akira Matsuda"]
12
+ s.date = %q{2011-02-06}
13
+ s.description = %q{Kaminari is a Scope & Engine based clean and powerful and customizable and sophisticated paginator for Rails 3}
14
+ s.email = %q{ronnie@dio.jp}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE.txt",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".rspec",
22
+ "Gemfile",
23
+ "Gemfile.lock",
24
+ "LICENSE.txt",
25
+ "README.rdoc",
26
+ "Rakefile",
27
+ "TODO.txt",
28
+ "VERSION",
29
+ "app/views/kaminari/_current_page.html.erb",
30
+ "app/views/kaminari/_first_page_link.html.erb",
31
+ "app/views/kaminari/_last_page_link.html.erb",
32
+ "app/views/kaminari/_next_link.html.erb",
33
+ "app/views/kaminari/_next_span.html.erb",
34
+ "app/views/kaminari/_page_link.html.erb",
35
+ "app/views/kaminari/_prev_link.html.erb",
36
+ "app/views/kaminari/_prev_span.html.erb",
37
+ "app/views/kaminari/_truncated_span.html.erb",
38
+ "kaminari.gemspec",
39
+ "lib/generators/kaminari/views_generator.rb",
40
+ "lib/kaminari.rb",
41
+ "lib/kaminari/active_record.rb",
42
+ "lib/kaminari/engine.rb",
43
+ "lib/kaminari/helpers.rb",
44
+ "lib/kaminari/railtie.rb",
45
+ "spec/controllers/application_helper_spec.rb",
46
+ "spec/helpers/helpers_spec.rb",
47
+ "spec/models/scopes_spec.rb",
48
+ "spec/spec_helper.rb",
49
+ "spec/support/20110128122508_create_users.rb",
50
+ "spec/support/matchers.rb",
51
+ "spec/support/user.rb"
52
+ ]
53
+ s.homepage = %q{http://github.com/amatsuda/kaminari}
54
+ s.licenses = ["MIT"]
55
+ s.require_paths = ["lib"]
56
+ s.rubygems_version = %q{1.4.2}
57
+ s.summary = %q{A pagnation engine plugin for Rails 3}
58
+ s.test_files = [
59
+ "spec/controllers/application_helper_spec.rb",
60
+ "spec/helpers/helpers_spec.rb",
61
+ "spec/models/scopes_spec.rb",
62
+ "spec/spec_helper.rb",
63
+ "spec/support/20110128122508_create_users.rb",
64
+ "spec/support/matchers.rb",
65
+ "spec/support/user.rb"
66
+ ]
67
+
68
+ if s.respond_to? :specification_version then
69
+ s.specification_version = 3
70
+
71
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
72
+ s.add_development_dependency(%q<rspec>, [">= 2.4.0"])
73
+ s.add_development_dependency(%q<rr>, [">= 1.0.2"])
74
+ s.add_development_dependency(%q<bundler>, [">= 1.0.0"])
75
+ s.add_development_dependency(%q<jeweler>, [">= 1.5.2"])
76
+ s.add_development_dependency(%q<rcov>, [">= 0"])
77
+ s.add_development_dependency(%q<rails>, [">= 0"])
78
+ s.add_development_dependency(%q<rack>, [">= 0"])
79
+ s.add_development_dependency(%q<arel>, [">= 0"])
80
+ s.add_development_dependency(%q<rspec-rails>, [">= 0"])
81
+ s.add_development_dependency(%q<sqlite3>, [">= 1.3.3"])
82
+ s.add_development_dependency(%q<ruby-debug>, [">= 0"])
83
+ s.add_runtime_dependency(%q<rails>, [">= 3.0.0"])
84
+ else
85
+ s.add_dependency(%q<rspec>, [">= 2.4.0"])
86
+ s.add_dependency(%q<rr>, [">= 1.0.2"])
87
+ s.add_dependency(%q<bundler>, [">= 1.0.0"])
88
+ s.add_dependency(%q<jeweler>, [">= 1.5.2"])
89
+ s.add_dependency(%q<rcov>, [">= 0"])
90
+ s.add_dependency(%q<rails>, [">= 0"])
91
+ s.add_dependency(%q<rack>, [">= 0"])
92
+ s.add_dependency(%q<arel>, [">= 0"])
93
+ s.add_dependency(%q<rspec-rails>, [">= 0"])
94
+ s.add_dependency(%q<sqlite3>, [">= 1.3.3"])
95
+ s.add_dependency(%q<ruby-debug>, [">= 0"])
96
+ s.add_dependency(%q<rails>, [">= 3.0.0"])
97
+ end
98
+ else
99
+ s.add_dependency(%q<rspec>, [">= 2.4.0"])
100
+ s.add_dependency(%q<rr>, [">= 1.0.2"])
101
+ s.add_dependency(%q<bundler>, [">= 1.0.0"])
102
+ s.add_dependency(%q<jeweler>, [">= 1.5.2"])
103
+ s.add_dependency(%q<rcov>, [">= 0"])
104
+ s.add_dependency(%q<rails>, [">= 0"])
105
+ s.add_dependency(%q<rack>, [">= 0"])
106
+ s.add_dependency(%q<arel>, [">= 0"])
107
+ s.add_dependency(%q<rspec-rails>, [">= 0"])
108
+ s.add_dependency(%q<sqlite3>, [">= 1.3.3"])
109
+ s.add_dependency(%q<ruby-debug>, [">= 0"])
110
+ s.add_dependency(%q<rails>, [">= 3.0.0"])
111
+ end
112
+ end
113
+
@@ -0,0 +1,12 @@
1
+ module Kaminari
2
+ module Generators
3
+ class ViewsGenerator < Rails::Generators::Base
4
+ source_root File.expand_path('../../../../app/views', __FILE__)
5
+
6
+ desc 'Copies all paginator partials to your application.'
7
+ def copy_views
8
+ directory 'kaminari', 'app/views/kaminari'
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,2 @@
1
+ require File.join(File.dirname(__FILE__), 'kaminari/railtie')
2
+ require File.join(File.dirname(__FILE__), 'kaminari/engine')
@@ -0,0 +1,37 @@
1
+ module Kaminari
2
+ module ActiveRecord
3
+ extend ActiveSupport::Concern
4
+ PER_PAGE = 10
5
+
6
+ included do
7
+ def self.inherited(kls)
8
+ # TERRIBLE HORRIBLE NO GOOD VERY BAD HACK: inheritable_attributes is not yet set here on AR 3.0
9
+ unless kls.default_scoping
10
+ new_inheritable_attributes = Hash[inheritable_attributes.map do |key, value|
11
+ [key, value.duplicable? ? value.dup : value]
12
+ end]
13
+ kls.instance_variable_set('@inheritable_attributes', new_inheritable_attributes)
14
+ end
15
+ kls.class_eval do
16
+ # page(5)
17
+ scope :page, lambda {|num|
18
+ offset(PER_PAGE * ([num.to_i, 1].max - 1)).limit(PER_PAGE)
19
+ } do
20
+ # page(3).per(20)
21
+ def per(num)
22
+ offset(offset_value / limit_value * num).limit(num)
23
+ end
24
+
25
+ def num_pages
26
+ (except(:offset, :limit).count.to_f / limit_value).ceil
27
+ end
28
+
29
+ def current_page
30
+ (offset_value / limit_value) + 1
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,4 @@
1
+ module Kaminari
2
+ class Engine < ::Rails::Engine
3
+ end
4
+ end
@@ -0,0 +1,105 @@
1
+ module Kaminari
2
+ module Helpers
3
+ class Tag
4
+ def initialize(renderer, options = {})
5
+ @renderer, @options = renderer, renderer.options.merge(options)
6
+ end
7
+
8
+ def to_s(locals = {})
9
+ @renderer.render :partial => "kaminari/#{self.class.name.demodulize.underscore}", :locals => @options.merge(locals)
10
+ end
11
+
12
+ private
13
+ def page_url_for(page)
14
+ @renderer.url_for @renderer.params.merge(:page => (page <= 1 ? nil : page))
15
+ end
16
+ end
17
+
18
+ class PrevSpan < Tag
19
+ end
20
+
21
+ class PrevLink < Tag
22
+ def to_s
23
+ super :prev_url => page_url_for(@options[:current_page] - 1)
24
+ end
25
+ end
26
+
27
+ class NextSpan < Tag
28
+ end
29
+
30
+ class NextLink < Tag
31
+ def to_s
32
+ super :next_url => page_url_for(@options[:current_page] + 1)
33
+ end
34
+ end
35
+
36
+ class PageLink < Tag
37
+ def to_s
38
+ super :page_url => page_url_for(@options[:page])
39
+ end
40
+ end
41
+
42
+ class CurrentPage < Tag
43
+ def to_s
44
+ super :page_url => page_url_for(@options[:page])
45
+ end
46
+ end
47
+
48
+ class FirstPageLink < PageLink
49
+ end
50
+
51
+ class LastPageLink < PageLink
52
+ end
53
+
54
+ class TruncatedSpan < Tag
55
+ end
56
+
57
+ class PaginationRenderer
58
+ attr_reader :options
59
+
60
+ def initialize(template, options)
61
+ @template, @options = template, options
62
+ @left, @window, @right = (options[:left] || options[:outer_window] || 1), (options[:window] || options[:inner_window] || 4), (options[:right] || options[:outer_window] || 1)
63
+ end
64
+
65
+ def to_s
66
+ @template.content_tag :div, :class => 'pagination' do
67
+ tagify.join("\n").html_safe
68
+ end
69
+ end
70
+
71
+ def tagify
72
+ num_pages, current_page, left, window, right = @options[:num_pages], @options[:current_page], @left, @window, @right
73
+
74
+ tags = []
75
+ tags << (current_page > 1 ? PrevLink.new(self) : PrevSpan.new(self))
76
+ 1.upto(num_pages) do |i|
77
+ if i == current_page
78
+ tags << CurrentPage.new(self, :page => i)
79
+ elsif (i <= left + 1) || ((num_pages - i) <= right) || ((i - current_page).abs <= window)
80
+ case i
81
+ when 1
82
+ tags << FirstPageLink.new(self, :page => i)
83
+ when num_pages
84
+ tags << LastPageLink.new(self, :page => i)
85
+ else
86
+ tags << PageLink.new(self, :page => i)
87
+ end
88
+ else
89
+ tags << TruncatedSpan.new(self) unless tags.last.is_a? TruncatedSpan
90
+ end
91
+ end
92
+ tags << (num_pages > current_page ? NextLink.new(self) : NextSpan.new(self))
93
+ end
94
+
95
+ private
96
+ def method_missing(meth, *args, &blk)
97
+ @template.send meth, *args, &blk
98
+ end
99
+ end
100
+
101
+ def paginate(scope, options = {}, &block)
102
+ PaginationRenderer.new self, options.reverse_merge(:current_page => scope.current_page, :num_pages => scope.num_pages)
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,14 @@
1
+ require 'rails'
2
+ require 'active_record'
3
+ require 'action_view'
4
+ require File.join(File.dirname(__FILE__), 'active_record')
5
+ require File.join(File.dirname(__FILE__), 'helpers')
6
+
7
+ module Kaminari
8
+ class Railtie < ::Rails::Railtie
9
+ initializer 'paginatablize' do |app|
10
+ ::ActiveRecord::Base.send :include, Kaminari::ActiveRecord
11
+ ::ActionView::Base.send :include, Kaminari::Helpers
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,21 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ class ApplicationController < ActionController::Base; end
4
+ class UsersController < ApplicationController
5
+ def index
6
+ @users = User.page params[:page]
7
+ render :inline => '<%= paginate @users %>'
8
+ end
9
+ end
10
+
11
+ describe UsersController, 'pagination' do
12
+ render_views
13
+ before do
14
+ 1.upto(30) {|i| User.create! :name => "user#{'%02d' % i}" }
15
+ end
16
+
17
+ it 'renders' do
18
+ get :index
19
+ response.body.should =~ /pagination/
20
+ end
21
+ end
@@ -0,0 +1,109 @@
1
+ require File.expand_path('../spec_helper', File.dirname(__FILE__))
2
+ include Kaminari::Helpers
3
+
4
+ describe 'Kaminari::Helpers::PaginationRenderer' do
5
+ let :renderer do
6
+ stub(r = Object.new) do
7
+ render.with_any_args
8
+ params { {} }
9
+ url_for {|h| "/foo?page=#{h[:page]}"}
10
+ end
11
+ r
12
+ end
13
+ describe '#tagify' do
14
+ def tags_with(options)
15
+ PaginationRenderer.new(renderer, options).tagify
16
+ end
17
+
18
+ context 'first page' do
19
+ subject { tags_with :num_pages => 10, :current_page => 1 }
20
+ it { should_not contain_tag PrevLink }
21
+ it { should contain_tag PrevSpan }
22
+ it { should contain_tag CurrentPage }
23
+ it { should_not contain_tag FirstPageLink }
24
+ it { should contain_tag LastPageLink }
25
+ it { should contain_tag PageLink }
26
+ it { should contain_tag NextLink }
27
+ it { should_not contain_tag NextSpan }
28
+ it { should contain_tag TruncatedSpan }
29
+ end
30
+
31
+ context 'second page' do
32
+ subject { tags_with :num_pages => 10, :current_page => 2 }
33
+ it { should contain_tag PrevLink }
34
+ it { should_not contain_tag PrevSpan }
35
+ it { should contain_tag CurrentPage }
36
+ it { should contain_tag FirstPageLink }
37
+ it { should contain_tag LastPageLink }
38
+ it { should contain_tag PageLink }
39
+ it { should contain_tag NextLink }
40
+ it { should_not contain_tag NextSpan }
41
+ it { should contain_tag TruncatedSpan }
42
+ end
43
+
44
+ context 'third page' do
45
+ subject { tags_with :num_pages => 10, :current_page => 3 }
46
+ it { should contain_tag PrevLink }
47
+ it { should_not contain_tag PrevSpan }
48
+ it { should contain_tag CurrentPage }
49
+ it { should contain_tag FirstPageLink }
50
+ it { should contain_tag LastPageLink }
51
+ it { should contain_tag PageLink }
52
+ it { should contain_tag NextLink }
53
+ it { should_not contain_tag NextSpan }
54
+ it { should contain_tag TruncatedSpan }
55
+ end
56
+
57
+ context 'fourth page(no truncation)' do
58
+ subject { tags_with :num_pages => 10, :current_page => 4 }
59
+ it { should contain_tag PrevLink }
60
+ it { should_not contain_tag PrevSpan }
61
+ it { should contain_tag CurrentPage }
62
+ it { should contain_tag FirstPageLink }
63
+ it { should contain_tag LastPageLink }
64
+ it { should contain_tag PageLink }
65
+ it { should contain_tag NextLink }
66
+ it { should_not contain_tag NextSpan }
67
+ it { should_not contain_tag TruncatedSpan }
68
+ end
69
+
70
+ context 'seventh page(no truncation)' do
71
+ subject { tags_with :num_pages => 10, :current_page => 7 }
72
+ it { should contain_tag PrevLink }
73
+ it { should_not contain_tag PrevSpan }
74
+ it { should contain_tag CurrentPage }
75
+ it { should contain_tag FirstPageLink }
76
+ it { should contain_tag LastPageLink }
77
+ it { should contain_tag PageLink }
78
+ it { should contain_tag NextLink }
79
+ it { should_not contain_tag NextSpan }
80
+ it { should_not contain_tag TruncatedSpan }
81
+ end
82
+
83
+ context 'eighth page' do
84
+ subject { tags_with :num_pages => 10, :current_page => 8 }
85
+ it { should contain_tag PrevLink }
86
+ it { should_not contain_tag PrevSpan }
87
+ it { should contain_tag CurrentPage }
88
+ it { should contain_tag FirstPageLink }
89
+ it { should contain_tag LastPageLink }
90
+ it { should contain_tag PageLink }
91
+ it { should contain_tag NextLink }
92
+ it { should_not contain_tag NextSpan }
93
+ it { should contain_tag TruncatedSpan }
94
+ end
95
+
96
+ context 'last page' do
97
+ subject { tags_with :num_pages => 10, :current_page => 10 }
98
+ it { should contain_tag PrevLink }
99
+ it { should_not contain_tag PrevSpan }
100
+ it { should contain_tag CurrentPage }
101
+ it { should contain_tag FirstPageLink }
102
+ it { should_not contain_tag LastPageLink }
103
+ it { should contain_tag PageLink }
104
+ it { should_not contain_tag NextLink }
105
+ it { should contain_tag NextSpan }
106
+ it { should contain_tag TruncatedSpan }
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,82 @@
1
+ require File.expand_path('../spec_helper', File.dirname(__FILE__))
2
+
3
+ describe Kaminari::ActiveRecord do
4
+ before :all do
5
+ User.delete_all
6
+ 1.upto(20) {|i| User.create! :name => "user#{'%02d' % i}" }
7
+ end
8
+
9
+ describe '#page' do
10
+ shared_examples_for 'the first page' do
11
+ it { should have(10).users }
12
+ its('first.name') { should == 'user01' }
13
+ end
14
+
15
+ shared_examples_for 'blank page' do
16
+ it { should have(0).users }
17
+ end
18
+
19
+ context 'page 1' do
20
+ subject { User.page 1 }
21
+ it_should_behave_like 'the first page'
22
+ end
23
+
24
+ context 'page 2' do
25
+ subject { User.page 2 }
26
+ it { should have(10).users }
27
+ its('first.name') { should == 'user11' }
28
+ end
29
+
30
+ context 'page without an argument' do
31
+ subject { User.page }
32
+ it_should_behave_like 'the first page'
33
+ end
34
+
35
+ context 'page < 1' do
36
+ subject { User.page 0 }
37
+ it_should_behave_like 'the first page'
38
+ end
39
+
40
+ context 'page > max page' do
41
+ subject { User.page 3 }
42
+ it_should_behave_like 'blank page'
43
+ end
44
+ end
45
+
46
+ describe '#per' do
47
+ context 'page 1 per 5' do
48
+ subject { User.page(1).per(5) }
49
+ it { should have(5).users }
50
+ its('first.name') { should == 'user01' }
51
+ end
52
+ end
53
+
54
+ describe '#num_pages' do
55
+ context 'per 10' do
56
+ subject { User.page.num_pages }
57
+ it { should == 2 }
58
+ end
59
+
60
+ context 'per 7' do
61
+ subject { User.page(2).per(7).num_pages }
62
+ it { should == 3 }
63
+ end
64
+
65
+ context 'per 65536' do
66
+ subject { User.page(50).per(65536).num_pages }
67
+ it { should == 1 }
68
+ end
69
+ end
70
+
71
+ describe '#current_page' do
72
+ context 'page 1' do
73
+ subject { User.page.current_page }
74
+ it { should == 1 }
75
+ end
76
+
77
+ context 'page 2' do
78
+ subject { User.page(2).per(3).current_page }
79
+ it { should == 2 }
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,37 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
3
+ require 'active_support/all'
4
+ require 'active_record'
5
+ require 'rails'
6
+ require 'action_controller/railtie'
7
+ require 'action_view/railtie'
8
+ require 'rspec/rails'
9
+
10
+ ActiveRecord::Base.configurations = {'test' => {:adapter => 'sqlite3', :database => ':memory:'}}
11
+ ActiveRecord::Base.establish_connection('test')
12
+
13
+ require 'kaminari'
14
+
15
+ app = Class.new(Rails::Application)
16
+ app.config.secret_token = "3b7cd727ee24e8444053437c36cc66c4"
17
+ app.config.session_store :cookie_store, :key => "_myapp_session"
18
+ app.config.active_support.deprecation = :log
19
+ app.initialize!
20
+
21
+ app.routes.draw do
22
+ resources :users
23
+ end
24
+
25
+ Object.const_set(:ApplicationHelper, Module.new)
26
+
27
+ # Requires supporting files with custom matchers and macros, etc,
28
+ # in ./support/ and its subdirectories.
29
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
30
+
31
+ RSpec.configure do |config|
32
+ config.mock_with :rr
33
+ config.before :all do
34
+ # ActiveRecord::Base.connection.execute 'CREATE TABLE "users" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar(255))' unless ActiveRecord::Base.connection.table_exists? 'users'
35
+ CreateUsers.up unless ActiveRecord::Base.connection.table_exists? 'users'
36
+ end
37
+ end
@@ -0,0 +1,8 @@
1
+ class CreateUsers < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :users do |t|
4
+ t.string :name
5
+ t.timestamps
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,40 @@
1
+ RSpec::Matchers.define :contain_tag do |klass|
2
+ match do |collection|
3
+ if @num.blank?
4
+ collection.any? {|tag| tag.is_a? klass}
5
+ else
6
+ (@count = collection.count {|tag| tag.is_a? klass}) == @num
7
+ end
8
+ end
9
+
10
+ def count(num)
11
+ @num = num
12
+ self
13
+ end
14
+
15
+ description do
16
+ "contain #{@num || 'any'} instance(s) of #{klass.name}"
17
+ end
18
+ failure_message_for_should do |collection|
19
+ "expected #{@num || 'any'} instance(s) of #{klass.name} but was #{@count}"
20
+ end
21
+ end
22
+
23
+ RSpec::Matchers.define :contain_tag_old do |count|
24
+ match do |collection|
25
+ (@count = collection.count {|tag| tag.is_a? @klass}) == count
26
+ end
27
+
28
+ def instance_of(klass)
29
+ @klass = klass
30
+ self
31
+ end
32
+ alias :instances_of :instance_of
33
+
34
+ description do
35
+ "contain #{count || 'any'} instance(s) of #{@klass.name}"
36
+ end
37
+ failure_message_for_should do |collection|
38
+ "expected #{count || 'any'} instance(s) of #{@klass.name} but was #{@count}"
39
+ end
40
+ end
@@ -0,0 +1,3 @@
1
+ class User < ActiveRecord::Base
2
+ default_scope order('name')
3
+ end
metadata ADDED
@@ -0,0 +1,284 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: kaminari
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Akira Matsuda
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-02-06 00:00:00 +09:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ type: :development
23
+ version_requirements: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ hash: 31
29
+ segments:
30
+ - 2
31
+ - 4
32
+ - 0
33
+ version: 2.4.0
34
+ requirement: *id001
35
+ prerelease: false
36
+ name: rspec
37
+ - !ruby/object:Gem::Dependency
38
+ type: :development
39
+ version_requirements: &id002 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ hash: 19
45
+ segments:
46
+ - 1
47
+ - 0
48
+ - 2
49
+ version: 1.0.2
50
+ requirement: *id002
51
+ prerelease: false
52
+ name: rr
53
+ - !ruby/object:Gem::Dependency
54
+ type: :development
55
+ version_requirements: &id003 !ruby/object:Gem::Requirement
56
+ none: false
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ hash: 23
61
+ segments:
62
+ - 1
63
+ - 0
64
+ - 0
65
+ version: 1.0.0
66
+ requirement: *id003
67
+ prerelease: false
68
+ name: bundler
69
+ - !ruby/object:Gem::Dependency
70
+ type: :development
71
+ version_requirements: &id004 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ hash: 7
77
+ segments:
78
+ - 1
79
+ - 5
80
+ - 2
81
+ version: 1.5.2
82
+ requirement: *id004
83
+ prerelease: false
84
+ name: jeweler
85
+ - !ruby/object:Gem::Dependency
86
+ type: :development
87
+ version_requirements: &id005 !ruby/object:Gem::Requirement
88
+ none: false
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ hash: 3
93
+ segments:
94
+ - 0
95
+ version: "0"
96
+ requirement: *id005
97
+ prerelease: false
98
+ name: rcov
99
+ - !ruby/object:Gem::Dependency
100
+ type: :development
101
+ version_requirements: &id006 !ruby/object:Gem::Requirement
102
+ none: false
103
+ requirements:
104
+ - - ">="
105
+ - !ruby/object:Gem::Version
106
+ hash: 3
107
+ segments:
108
+ - 0
109
+ version: "0"
110
+ requirement: *id006
111
+ prerelease: false
112
+ name: rails
113
+ - !ruby/object:Gem::Dependency
114
+ type: :development
115
+ version_requirements: &id007 !ruby/object:Gem::Requirement
116
+ none: false
117
+ requirements:
118
+ - - ">="
119
+ - !ruby/object:Gem::Version
120
+ hash: 3
121
+ segments:
122
+ - 0
123
+ version: "0"
124
+ requirement: *id007
125
+ prerelease: false
126
+ name: rack
127
+ - !ruby/object:Gem::Dependency
128
+ type: :development
129
+ version_requirements: &id008 !ruby/object:Gem::Requirement
130
+ none: false
131
+ requirements:
132
+ - - ">="
133
+ - !ruby/object:Gem::Version
134
+ hash: 3
135
+ segments:
136
+ - 0
137
+ version: "0"
138
+ requirement: *id008
139
+ prerelease: false
140
+ name: arel
141
+ - !ruby/object:Gem::Dependency
142
+ type: :development
143
+ version_requirements: &id009 !ruby/object:Gem::Requirement
144
+ none: false
145
+ requirements:
146
+ - - ">="
147
+ - !ruby/object:Gem::Version
148
+ hash: 3
149
+ segments:
150
+ - 0
151
+ version: "0"
152
+ requirement: *id009
153
+ prerelease: false
154
+ name: rspec-rails
155
+ - !ruby/object:Gem::Dependency
156
+ type: :development
157
+ version_requirements: &id010 !ruby/object:Gem::Requirement
158
+ none: false
159
+ requirements:
160
+ - - ">="
161
+ - !ruby/object:Gem::Version
162
+ hash: 29
163
+ segments:
164
+ - 1
165
+ - 3
166
+ - 3
167
+ version: 1.3.3
168
+ requirement: *id010
169
+ prerelease: false
170
+ name: sqlite3
171
+ - !ruby/object:Gem::Dependency
172
+ type: :development
173
+ version_requirements: &id011 !ruby/object:Gem::Requirement
174
+ none: false
175
+ requirements:
176
+ - - ">="
177
+ - !ruby/object:Gem::Version
178
+ hash: 3
179
+ segments:
180
+ - 0
181
+ version: "0"
182
+ requirement: *id011
183
+ prerelease: false
184
+ name: ruby-debug
185
+ - !ruby/object:Gem::Dependency
186
+ type: :runtime
187
+ version_requirements: &id012 !ruby/object:Gem::Requirement
188
+ none: false
189
+ requirements:
190
+ - - ">="
191
+ - !ruby/object:Gem::Version
192
+ hash: 7
193
+ segments:
194
+ - 3
195
+ - 0
196
+ - 0
197
+ version: 3.0.0
198
+ requirement: *id012
199
+ prerelease: false
200
+ name: rails
201
+ description: Kaminari is a Scope & Engine based clean and powerful and customizable and sophisticated paginator for Rails 3
202
+ email: ronnie@dio.jp
203
+ executables: []
204
+
205
+ extensions: []
206
+
207
+ extra_rdoc_files:
208
+ - LICENSE.txt
209
+ - README.rdoc
210
+ files:
211
+ - .document
212
+ - .rspec
213
+ - Gemfile
214
+ - Gemfile.lock
215
+ - LICENSE.txt
216
+ - README.rdoc
217
+ - Rakefile
218
+ - TODO.txt
219
+ - VERSION
220
+ - app/views/kaminari/_current_page.html.erb
221
+ - app/views/kaminari/_first_page_link.html.erb
222
+ - app/views/kaminari/_last_page_link.html.erb
223
+ - app/views/kaminari/_next_link.html.erb
224
+ - app/views/kaminari/_next_span.html.erb
225
+ - app/views/kaminari/_page_link.html.erb
226
+ - app/views/kaminari/_prev_link.html.erb
227
+ - app/views/kaminari/_prev_span.html.erb
228
+ - app/views/kaminari/_truncated_span.html.erb
229
+ - kaminari.gemspec
230
+ - lib/generators/kaminari/views_generator.rb
231
+ - lib/kaminari.rb
232
+ - lib/kaminari/active_record.rb
233
+ - lib/kaminari/engine.rb
234
+ - lib/kaminari/helpers.rb
235
+ - lib/kaminari/railtie.rb
236
+ - spec/controllers/application_helper_spec.rb
237
+ - spec/helpers/helpers_spec.rb
238
+ - spec/models/scopes_spec.rb
239
+ - spec/spec_helper.rb
240
+ - spec/support/20110128122508_create_users.rb
241
+ - spec/support/matchers.rb
242
+ - spec/support/user.rb
243
+ has_rdoc: true
244
+ homepage: http://github.com/amatsuda/kaminari
245
+ licenses:
246
+ - MIT
247
+ post_install_message:
248
+ rdoc_options: []
249
+
250
+ require_paths:
251
+ - lib
252
+ required_ruby_version: !ruby/object:Gem::Requirement
253
+ none: false
254
+ requirements:
255
+ - - ">="
256
+ - !ruby/object:Gem::Version
257
+ hash: 3
258
+ segments:
259
+ - 0
260
+ version: "0"
261
+ required_rubygems_version: !ruby/object:Gem::Requirement
262
+ none: false
263
+ requirements:
264
+ - - ">="
265
+ - !ruby/object:Gem::Version
266
+ hash: 3
267
+ segments:
268
+ - 0
269
+ version: "0"
270
+ requirements: []
271
+
272
+ rubyforge_project:
273
+ rubygems_version: 1.4.2
274
+ signing_key:
275
+ specification_version: 3
276
+ summary: A pagnation engine plugin for Rails 3
277
+ test_files:
278
+ - spec/controllers/application_helper_spec.rb
279
+ - spec/helpers/helpers_spec.rb
280
+ - spec/models/scopes_spec.rb
281
+ - spec/spec_helper.rb
282
+ - spec/support/20110128122508_create_users.rb
283
+ - spec/support/matchers.rb
284
+ - spec/support/user.rb