simple_paginate 0.0.1

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.
Files changed (45) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +39 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE +22 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +77 -0
  7. data/Rakefile +50 -0
  8. data/app/views/simple_paginate/_next_page.html.erb +9 -0
  9. data/app/views/simple_paginate/_next_page.html.haml +7 -0
  10. data/app/views/simple_paginate/_next_page.html.slim +7 -0
  11. data/app/views/simple_paginate/_paginator.html.erb +12 -0
  12. data/app/views/simple_paginate/_paginator.html.haml +9 -0
  13. data/app/views/simple_paginate/_paginator.html.slim +9 -0
  14. data/app/views/simple_paginate/_prev_page.html.erb +9 -0
  15. data/app/views/simple_paginate/_prev_page.html.haml +7 -0
  16. data/app/views/simple_paginate/_prev_page.html.slim +7 -0
  17. data/config/locales/simple_paginate.yml +5 -0
  18. data/gemfiles/.bundle/config +2 -0
  19. data/gemfiles/active_record_42.gemfile +24 -0
  20. data/gemfiles/active_record_42.gemfile.lock +319 -0
  21. data/lib/generators/simple_paginate/config_generator.rb +16 -0
  22. data/lib/generators/simple_paginate/templates/simple_paginate_config.rb +3 -0
  23. data/lib/generators/simple_paginate/views_generator.rb +31 -0
  24. data/lib/simple_paginate/config.rb +21 -0
  25. data/lib/simple_paginate/engine.rb +4 -0
  26. data/lib/simple_paginate/helpers/action_view_extension.rb +19 -0
  27. data/lib/simple_paginate/helpers/paginator.rb +70 -0
  28. data/lib/simple_paginate/helpers/tags.rb +84 -0
  29. data/lib/simple_paginate/models/active_record_extension.rb +27 -0
  30. data/lib/simple_paginate/railtie.rb +16 -0
  31. data/lib/simple_paginate/version.rb +3 -0
  32. data/lib/simple_paginate.rb +9 -0
  33. data/simple_paginate.gemspec +28 -0
  34. data/spec/fake_app/active_record/config.rb +3 -0
  35. data/spec/fake_app/active_record/models.rb +12 -0
  36. data/spec/fake_app/log/development.log +0 -0
  37. data/spec/fake_app/rails_app.rb +38 -0
  38. data/spec/simple_paginate/config_spec.rb +27 -0
  39. data/spec/simple_paginate/helpers/action_view_extension_spec.rb +43 -0
  40. data/spec/simple_paginate/helpers/tags_spec.rb +57 -0
  41. data/spec/simple_paginate/models/active_record_extension_spec.rb +71 -0
  42. data/spec/simple_paginate/version_spec.rb +8 -0
  43. data/spec/spec_helper.rb +19 -0
  44. data/spec/support/database_cleaner.rb +12 -0
  45. metadata +182 -0
@@ -0,0 +1,3 @@
1
+ SimplePaginte.configure do |config|
2
+ # config.default_per_page = 25
3
+ end
@@ -0,0 +1,31 @@
1
+ module SimplePaginate
2
+ module Generators
3
+
4
+ class ViewsGenerator < Rails::Generators::Base
5
+ source_root File.expand_path('../../../../app/views/simple_paginate', __FILE__)
6
+
7
+ class_option :template_engine, :type => :string, :aliases => '-e', :desc => 'Template engine for the views. Available options are "erb", "haml", and "slim".'
8
+
9
+ def self.banner #:nodoc:
10
+ <<-BANNER.chomp
11
+ rails g simple_paginate:views [options]
12
+
13
+ Copies all paginator partial templates to your application.
14
+ BANNER
15
+ end
16
+
17
+ def copy_views
18
+ filename_pattern = File.join self.class.source_root, "*.html.#{template_engine}"
19
+ Dir.glob(filename_pattern).map {|f| File.basename f}.each do |f|
20
+ copy_file f, "app/views/simple_paginate/#{f}"
21
+ end
22
+ end
23
+
24
+ private
25
+
26
+ def template_engine
27
+ options[:template_engine].try(:to_s).try(:downcase) || 'erb'
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,21 @@
1
+ require 'active_support/configurable'
2
+
3
+ module SimplePaginate
4
+ def self.configure(&block)
5
+ yield @config ||= SimplePaginate::Configuration.new
6
+ end
7
+
8
+ def self.config
9
+ @config
10
+ end
11
+
12
+ class Configuration
13
+ include ActiveSupport::Configurable
14
+
15
+ config_accessor :default_per_page
16
+ end
17
+
18
+ configure do |config|
19
+ config.default_per_page = 25
20
+ end
21
+ end
@@ -0,0 +1,4 @@
1
+ module SimplePaginate
2
+ class Engine < ::Rails::Engine
3
+ end
4
+ end
@@ -0,0 +1,19 @@
1
+ module SimplePaginate
2
+ module ActionViewExtension
3
+ # A helper that renders the pagination links
4
+ def simple_paginate(scope, options = {})
5
+ paginator = SimplePaginate::Helpers::Paginator.new self, options.reverse_merge(current_page: scope.current_page, per_page: scope.limit_value, length: scope.length)
6
+ paginator.to_s
7
+ end
8
+
9
+ def link_to_previous_page(scope, name = nil, options = {})
10
+ prev_page = SimplePaginate::Helpers::PrevPage.new self, options.reverse_merge(:current_page => scope.current_page)
11
+ link_to_unless scope.first_page?, name, prev_page.url, options.except(:params, :param_name).reverse_merge(:rel => 'prev')
12
+ end
13
+
14
+ def link_to_next_page(scope, name = nil, options = {})
15
+ next_page = SimplePaginate::Helpers::NextPage.new self, options.reverse_merge(:current_page => scope.current_page)
16
+ link_to_unless scope.last_page?, name, next_page.url, options.except(:params, :param_name).reverse_merge(:rel => 'next')
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,70 @@
1
+ require 'action_view'
2
+ require 'simple_paginate/helpers/tags'
3
+
4
+ module SimplePaginate
5
+ module Helpers
6
+ class Paginator < Tag
7
+ include ActionView::Context
8
+
9
+ def initialize(template, options)
10
+ super template, options.merge(current_page: PageProxy.new(options))
11
+ @output_buffer = ActionView::OutputBuffer.new
12
+ end
13
+
14
+ def render(&block)
15
+ instance_eval(&block)
16
+ @output_buffer
17
+ end
18
+
19
+ def prev_page_tag
20
+ PrevPage.new @template, @options
21
+ end
22
+
23
+ def next_page_tag
24
+ NextPage.new @template, @options
25
+ end
26
+
27
+ def to_s
28
+ super @options.merge(paginator: self)
29
+ end
30
+
31
+ class PageProxy
32
+ def initialize(options)
33
+ @options = options
34
+ end
35
+
36
+ def number
37
+ @options[:current_page]
38
+ end
39
+
40
+ def first?
41
+ @options[:current_page] == 1
42
+ end
43
+
44
+ def last?
45
+ @options[:length] < @options[:per_page]
46
+ end
47
+
48
+ def to_i
49
+ number
50
+ end
51
+
52
+ def to_s
53
+ number.to_s
54
+ end
55
+
56
+ def +(other)
57
+ to_i + other.to_i
58
+ end
59
+
60
+ def -(other)
61
+ to_i - other.to_i
62
+ end
63
+
64
+ def <=>(other)
65
+ to_i <=> other.to_i
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,84 @@
1
+ module SimplePaginate
2
+ module Helpers
3
+ PARAM_KEY_BLACKLIST = :authenticity_token, :commit, :utf8, :_method
4
+ PARAM_NAME = 'page'
5
+
6
+ class Tag
7
+ def initialize(template, options = {})
8
+ @template, @options = template, options
9
+ @views_prefix = @options.delete(:views_prefix)
10
+ @params = template.params.except(*PARAM_KEY_BLACKLIST).merge(@options.delete(:params) || {})
11
+ end
12
+
13
+ def to_s(locals = {})
14
+ @template.render partial: partial_path, locals: @options.merge(locals), formats: [:html]
15
+ end
16
+
17
+ def page_url_for(page)
18
+ @template.url_for params_for(page).merge(only_path: true)
19
+ end
20
+
21
+ private
22
+
23
+ def params_for(page)
24
+ page_params = Rack::Utils.parse_nested_query("#{PARAM_NAME}=#{page}")
25
+ page_params = @params.with_indifferent_access.deep_merge(page_params)
26
+
27
+ if page <= 1
28
+ PARAM_NAME.to_s.scan(/\w+/)[0..-2].inject(page_params){|h, k| h[k] }[$&] = nil
29
+ end
30
+
31
+ page_params
32
+ end
33
+
34
+ def partial_path
35
+ [@views_prefix,
36
+ 'simple_paginate',
37
+ self.class.name.demodulize.underscore
38
+ ].compact.join('/')
39
+ end
40
+ end
41
+
42
+ module Link
43
+ def page
44
+ raise 'Override page with the actual page value to be a Page.'
45
+ end
46
+
47
+ def url
48
+ page_url_for(page)
49
+ end
50
+
51
+ def to_s(locals = {})
52
+ super locals.merge(url: url)
53
+ end
54
+ end
55
+
56
+ class Page < Tag
57
+ include Link
58
+
59
+ def page
60
+ @options[:page]
61
+ end
62
+
63
+ def to_s(locals = {})
64
+ super locals.merge(page: page)
65
+ end
66
+ end
67
+
68
+ class PrevPage < Tag
69
+ include Link
70
+
71
+ def page
72
+ @options[:current_page] - 1
73
+ end
74
+ end
75
+
76
+ class NextPage < Tag
77
+ include Link
78
+
79
+ def page
80
+ @options[:current_page] + 1
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,27 @@
1
+ module SimplePaginate
2
+ module ActiveRecordExtension
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ def self.paginate(options = {})
7
+ options = options.dup
8
+ page = options.delete(:page) || 1
9
+ per_page = options.delete(:per_page) || SimplePaginate.config.default_per_page
10
+
11
+ offset(per_page * (page - 1)).limit(per_page + 1).extending do
12
+ def current_page
13
+ (offset_value / (limit_value - 1)) + 1
14
+ end
15
+
16
+ def first_page?
17
+ current_page == 1
18
+ end
19
+
20
+ def last_page?
21
+ length < limit_value
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,16 @@
1
+ module SimplePaginate
2
+ class Railtie < Rails::Railtie
3
+ initializer 'simple_paginate' do |app|
4
+ ActiveSupport.on_load :active_record do
5
+ require 'simple_paginate/models/active_record_extension'
6
+ ::ActiveRecord::Base.send :include, SimplePaginate::ActiveRecordExtension
7
+ end
8
+
9
+ ActiveSupport.on_load :action_view do
10
+ require 'simple_paginate/helpers/action_view_extension'
11
+ require 'simple_paginate/helpers/paginator'
12
+ ::ActionView::Base.send :include, SimplePaginate::ActionViewExtension
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,3 @@
1
+ module SimplePaginate
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,9 @@
1
+ module SimplePaginate
2
+ end
3
+
4
+ if defined?(Rails::Railtie)
5
+ require 'simple_paginate/railtie'
6
+ require 'simple_paginate/engine'
7
+ end
8
+
9
+ require 'simple_paginate/config'
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'simple_paginate/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "simple_paginate"
8
+ spec.version = SimplePaginate::VERSION
9
+ spec.authors = ["Yong Gu"]
10
+ spec.email = ["zerogy921@gmail.com"]
11
+ spec.summary = %q{Simple pagination solution for previous and next page navigation.}
12
+ spec.description = %q{Simple pagination solution for previous and next page navigation.}
13
+ spec.homepage = ""
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 'activesupport', ['>= 3.0.0']
22
+ spec.add_dependency 'actionpack', ['>= 3.0.0']
23
+
24
+ spec.add_development_dependency "bundler", "~> 1.6"
25
+ spec.add_development_dependency "rake"
26
+ spec.add_development_dependency "rspec", "~> 3.2"
27
+ spec.add_development_dependency 'database_cleaner', ['~> 1.4.0']
28
+ end
@@ -0,0 +1,3 @@
1
+ # database
2
+ ActiveRecord::Base.configurations = {'test' => {:adapter => 'sqlite3', :database => ':memory:'}}
3
+ ActiveRecord::Base.establish_connection :test
@@ -0,0 +1,12 @@
1
+ # models
2
+ class User < ActiveRecord::Base
3
+ end
4
+
5
+ #migrations
6
+ class CreateAllTables < ActiveRecord::Migration
7
+ def self.up
8
+ create_table(:users) {|t| t.string :name; t.integer :age}
9
+ end
10
+ end
11
+ ActiveRecord::Migration.verbose = false
12
+ CreateAllTables.up
File without changes
@@ -0,0 +1,38 @@
1
+ require 'action_controller/railtie'
2
+ require 'action_view/railtie'
3
+
4
+ require 'fake_app/active_record/config'
5
+ # config
6
+ app = Class.new(Rails::Application)
7
+ app.config.secret_key_base = '9489b3eee4eccf317ed77407553e8adc97baca7c74dc7ee33cd93e4c8b69477eea66eaedeb18af0be2679887c7c69c0a28c0fded0a71ea472a8c4laalal19cb'
8
+ app.config.secret_token = '3b7cd727ee24e8444053437c36cc66c4'
9
+ app.config.session_store :cookie_store, :key => '_myapp_session'
10
+ app.config.active_support.deprecation = :log
11
+ app.config.eager_load = false
12
+ # Rais.root
13
+ app.config.root = File.dirname(__FILE__)
14
+ Rails.backtrace_cleaner.remove_silencers!
15
+ app.initialize!
16
+
17
+ # routes
18
+ app.routes.draw do
19
+ resources :users
20
+ end
21
+
22
+ #models
23
+ require 'fake_app/active_record/models'
24
+
25
+ # controllers
26
+ class ApplicationController < ActionController::Base; end
27
+ class UsersController < ApplicationController
28
+ def index
29
+ @users = User.paginate page: params[:page]
30
+ render :inline => <<-ERB
31
+ <%= @users.map(&:name).join("\n") %>
32
+ <%= simple_paginate @users %>
33
+ ERB
34
+ end
35
+ end
36
+
37
+ # helpers
38
+ Object.const_set(:ApplicationHelper, Module.new)
@@ -0,0 +1,27 @@
1
+ require 'spec_helper'
2
+
3
+ describe SimplePaginate::Configuration do
4
+ subject { SimplePaginate.config }
5
+
6
+ describe 'default_per_page' do
7
+ context 'by default' do
8
+ it { expect(subject.default_per_page).to eq 25 }
9
+ end
10
+
11
+ context 'configured via config block' do
12
+ before do
13
+ SimplePaginate.configure do |config|
14
+ config.default_per_page = 20
15
+ end
16
+ end
17
+
18
+ it { expect(subject.default_per_page).to eq 25 }
19
+
20
+ before do
21
+ SimplePaginate.configure do |config|
22
+ config.default_per_page = 25
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,43 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'SimplePaginate::ActionViewExtension', type: :helper do
4
+ before :all do
5
+ 1.upto(100) {|i| User.create name: "user#{'%03d' % i}"}
6
+ end
7
+
8
+ after :all do
9
+ DatabaseCleaner.clean_with(:truncation)
10
+ end
11
+
12
+ describe '#link_to_previous_page' do
13
+ subject { helper.link_to_previous_page users, 'Previous Page', params: { controller: 'users', action: 'index' } }
14
+
15
+ context 'having previous pages' do
16
+ let(:users) { User.paginate(page: 3) }
17
+
18
+ it { expect(subject).to eq('<a rel="prev" href="/users?page=2">Previous Page</a>') }
19
+ end
20
+
21
+ context 'the first page' do
22
+ let(:users) { User.paginate(page: 1) }
23
+
24
+ it { expect(subject).to eq('Previous Page') }
25
+ end
26
+ end
27
+
28
+ describe '#link_to_next_page' do
29
+ subject { helper.link_to_next_page users, 'Next Page', params: { controller: 'users', action: 'index' } }
30
+
31
+ context 'having next pages' do
32
+ let(:users) { User.paginate(page: 3) }
33
+
34
+ it { expect(subject).to eq('<a rel="next" href="/users?page=4">Next Page</a>') }
35
+ end
36
+
37
+ context 'the last page' do
38
+ let(:users) { User.paginate(page: 4) }
39
+
40
+ it { expect(subject).to eq('Next Page') }
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,57 @@
1
+ require 'spec_helper'
2
+ include SimplePaginate::Helpers
3
+
4
+ describe 'SimplePaginate::Helpers', type: :helper do
5
+ describe 'Tag' do
6
+ describe '#page_url_for' do
7
+ before { helper.request.assign_parameters(_routes, 'users', 'index') }
8
+
9
+ context 'for first page' do
10
+ subject { Tag.new(helper).page_url_for(1) }
11
+ it { expect(subject).to eq('/users') }
12
+ end
13
+
14
+ context 'with a friendly route setting' do
15
+ before do
16
+ helper.request.assign_parameters(_routes, 'users', 'index', page: 3)
17
+ end
18
+
19
+ context 'for first page' do
20
+ subject { Tag.new(helper).page_url_for(1) }
21
+ it { expect(subject).to eq('/users') }
22
+ end
23
+
24
+ context 'for other page' do
25
+ subject { Tag.new(helper).page_url_for(5) }
26
+ it { expect(subject).to eq('/users?page=5') }
27
+ end
28
+ end
29
+ end
30
+ end
31
+
32
+ describe 'Paginator' do
33
+ describe 'Paginator::PageProxy' do
34
+ describe '#first?' do
35
+ context 'page == 1' do
36
+ subject { Paginator::PageProxy.new(current_page: 1, length: 20, per_page: 25) }
37
+ it { expect(subject.first?).to be_truthy }
38
+ end
39
+ context 'page != 1' do
40
+ subject { Paginator::PageProxy.new(current_page: 5, length: 20, per_page: 25) }
41
+ it { expect(subject.first?).to be_falsey }
42
+ end
43
+ end
44
+
45
+ describe '#last?' do
46
+ context 'length == per_page' do
47
+ subject { Paginator::PageProxy.new(current_page: 5, length: 25, per_page: 25) }
48
+ it { expect(subject.last?).to be_falsey}
49
+ end
50
+ context 'length < per_page' do
51
+ subject { Paginator::PageProxy.new(current_page: 5, length: 20, per_page: 25) }
52
+ it { expect(subject.last?).to be_truthy }
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,71 @@
1
+ require 'spec_helper'
2
+
3
+ describe SimplePaginate::ActiveRecordExtension do
4
+ before :all do
5
+ 1.upto(100) {|i| User.create name: "user#{'%03d' % i}"}
6
+ end
7
+
8
+ after :all do
9
+ DatabaseCleaner.clean_with(:truncation)
10
+ end
11
+
12
+ describe '#paginate' do
13
+ subject { User.paginate(page: page) }
14
+
15
+ context 'page 1' do
16
+ let(:page) { 1 }
17
+
18
+ it { expect(subject.first.name).to eq('user001') }
19
+ end
20
+
21
+ context 'page 2' do
22
+ let(:page) { 2 }
23
+
24
+ it { expect(subject.first.name).to eq('user026') }
25
+ end
26
+
27
+ context 'page < 1' do
28
+ let(:page) { 0 }
29
+
30
+ it { expect(subject.first.name).to eq('user001') }
31
+ end
32
+
33
+ context 'page > max page' do
34
+ let(:page) { 5 }
35
+
36
+ it { expect(subject).to be_empty }
37
+ end
38
+ end
39
+
40
+ describe '#current_page' do
41
+ context 'page 1' do
42
+ subject { User.paginate(page: 1) }
43
+ it { expect(subject.current_page).to eq 1 }
44
+ end
45
+ end
46
+
47
+ describe '#first_page?' do
48
+ context 'on first page' do
49
+ subject { User.paginate(page: 1) }
50
+ it { expect(subject.first_page?).to be_truthy }
51
+ end
52
+
53
+ context 'not on first page' do
54
+ subject { User.paginate(page: 2) }
55
+ it { expect(subject.first_page?).to be_falsey }
56
+ end
57
+ end
58
+
59
+ describe '#last_page?' do
60
+ context 'on last page' do
61
+ subject { User.paginate(page: 4) }
62
+
63
+ it { expect(subject.last_page?).to be_truthy }
64
+ end
65
+
66
+ context 'not on last page' do
67
+ subject { User.paginate(page: 3) }
68
+ it { expect(subject.last_page?).to be_falsey }
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,8 @@
1
+ require 'spec_helper'
2
+
3
+ describe SimplePaginate::VERSION do
4
+ it 'returns right value' do
5
+ expect(SimplePaginate::VERSION).to eq('0.0.1')
6
+ end
7
+ end
8
+
@@ -0,0 +1,19 @@
1
+ begin
2
+ require 'rails'
3
+ rescue LoadError
4
+ end
5
+
6
+ require 'bundler/setup'
7
+ Bundler.require
8
+
9
+ require 'database_cleaner'
10
+ require 'fake_app/rails_app'
11
+ require 'rspec/rails'
12
+
13
+ # Requires supporting files with custom matchers and macros, etc,
14
+ # in ./support/ and its subdirectories.
15
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
16
+
17
+ RSpec.configure do |config|
18
+ config.infer_spec_type_from_file_location!
19
+ end
@@ -0,0 +1,12 @@
1
+ RSpec.configure do |config|
2
+ config.before :suite do
3
+ DatabaseCleaner.strategy = :transaction
4
+ DatabaseCleaner.clean_with :truncation
5
+ end
6
+
7
+ config.around(:each) do |example|
8
+ DatabaseCleaner.cleaning do
9
+ example.run
10
+ end
11
+ end
12
+ end