cursor_pagination 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: 0975daf496d378c472103614276ccbcb01b30c9c
4
+ data.tar.gz: 054a13ee7d3149d8b0174b1ff776219c1be0443c
5
+ SHA512:
6
+ metadata.gz: ce77e48e37546b7c6192ab9f5e5a4b25f10b4dbfe1f78d87d9e24a9b9608cc96d02475b4f3adc1924c607197d1c443c88e169bf5da12ac0ce0d14d17b6d3cfee
7
+ data.tar.gz: 9e6024bf149e93ef1762e56964145172a892cb4ece9ea8c349bd3cead53330be9b3cc30dcf98927209c883c5159aab4a4f468496072c451d5f8ba5fbba084af0
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in cursor_pagination.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Sergey Kukunin
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,105 @@
1
+ # CursorPagination
2
+
3
+ ActiveRecord plugin for cursor based pagination. It uses specific model's column and rpp (results per page) to paginate your content.
4
+
5
+ The main advantage against traditional pagination (limmit and offset), that the one URL on specific page will contain the data set, despite the newly added entities. It may be useful on the projects, where new entities are added often, and specific page now isn't specific page tomorrow.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'cursor_pagination'
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install cursor_pagination
20
+
21
+ ## Usage
22
+
23
+ Just use `cursor` scope on your model chain:
24
+
25
+ User.where(active: true).cursor(params[:cursor]).per(20)
26
+
27
+ It will get 20 users by passed cursor. You can omit `per` scope:
28
+
29
+ User.where(active: true).cursor(params[:cursor])
30
+
31
+ In this case, the limit of entities per page will be 25 by default.
32
+
33
+ You can pass options as second argument for `cursor` scope
34
+
35
+ User.order('id DESC').cursor(params[:cursor], reverse: true).per(20)
36
+
37
+ ## How it works?
38
+
39
+ Actually, cursor is column value of specific entity, it uses to get all entities, later than specific. For example, if you have the Users set with IDs from 1 to 5,
40
+
41
+ User.cursor(2).per(20)
42
+
43
+ will return maximum 20 users after ID 2 (in this case, users with IDs 3, 4 and 5).
44
+
45
+ **Make sure that your objects are ordered by cursored column. If you use DESC order, use `reverse: true` option in `cursor` scope.**
46
+
47
+ ## Options
48
+
49
+ At this point, `cursor` scope accepts these options:
50
+
51
+ * `reverse`: Set it to true, if your set are ordered descendingly (_DESC_). Default: _false_
52
+ * `column`: column value of cursor. For example, if you order your data set by *updated_at*, set *updated_at* column for cursor. Default: _id_
53
+
54
+ ## Scope methods
55
+
56
+ * `first_page?/last_page?` - **true/false**
57
+
58
+ ```
59
+ @users = User.cursor(params[:cursor]).per(20)
60
+ @users.first_page?
61
+ ```
62
+
63
+ * `next_cursor/previous_cursor` - **cursor, nil or -1**. Returns the column value for cursor of next/previous page.
64
+ _nil_ is valid cursor too. It means first page. If cursor is unavailable (there isn't pages anymore), returns _-1_.
65
+
66
+ ## Helpers
67
+
68
+ * `next_cursor_url/previous_cursor_url` - **string**
69
+
70
+ ```
71
+ next_cursor_url(scope, url_options = {})
72
+ previous_cursor_url(scope, url_options = {})
73
+ ```
74
+
75
+ Returns the URL for next/previous cursor page or nil, if there isn't next/previous cursor available.
76
+
77
+ ```
78
+ <%= next_cursor_url(@users) %> # users/?cursor=3
79
+ <%= previous_cursor_url(@users) %> # users/?cursor=1
80
+ ```
81
+
82
+ * `next_cursor_link/previous_cursor_link` - **string**
83
+
84
+ ```
85
+ next_cursor_link(scope, name, url_options = {}, html_options = {})
86
+ previous_cursor_link(scope, name, url_options = {}, html_options = {})
87
+ ```
88
+
89
+ Returns the A html element with URL on next/previous cursor or nil, if there isn't next/previous cursor available. Accepts the same arguments, as `link_to` helper method, but scope object as first argument.
90
+
91
+ ```
92
+ # <a href="users/?cursor=3" rel="next">Next Page</a>
93
+ <%= next_cursor_link(scope, 'Next Page') %>
94
+ # <a href="users/?cursor=1" rel="previous">Previous Page</a>
95
+ <%= previous_cursor_link(scope, 'Previous Page') %>
96
+ ```
97
+
98
+
99
+ ## Contributing
100
+
101
+ 1. Fork it
102
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
103
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
104
+ 4. Push to the branch (`git push origin my-new-feature`)
105
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,3 @@
1
+ module CursorPaginationHelper
2
+ include CursorPagination::ActionViewHelper
3
+ end
@@ -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 'cursor_pagination/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "cursor_pagination"
8
+ spec.version = CursorPagination::VERSION
9
+ spec.authors = ["Sergey Kukunin"]
10
+ spec.email = ["sergey.kukunin@gmail.com"]
11
+ spec.description = %q{ActiveRecord plugin for cursor based pagination. Uses some column and rpp (results per page) to paginate your content. The main advantage against traditional pagination (limmit and offset), that the one URL on specific page will contain the data set, despite the newly added entities. It may be useful on the projects, where new entities are added often, and specific page now isn't specific page tomorrow.}
12
+ spec.summary = %q{ActiveRecord plugin for cursor based pagination}
13
+ spec.homepage = "https://github.com/Kukunin/cursor_pagination"
14
+ spec.license = "MIT"
15
+
16
+ spec.add_dependency "activerecord", ['>= 3.0.0']
17
+ spec.add_development_dependency "rspec-rails"
18
+ spec.add_development_dependency "sqlite3-ruby"
19
+ spec.add_development_dependency "database_cleaner", ['< 1.1.1']
20
+
21
+ spec.files = `git ls-files`.split($/)
22
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
23
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
24
+ spec.require_paths = ["lib"]
25
+
26
+ spec.add_development_dependency "bundler", "~> 1.3"
27
+ spec.add_development_dependency "rake"
28
+ end
@@ -0,0 +1,7 @@
1
+ require "cursor_pagination/version"
2
+ require "cursor_pagination/active_record_extension"
3
+ require 'cursor_pagination/action_view_helper'
4
+
5
+ module CursorPagination
6
+ ::ActiveRecord::Base.send(:include, CursorPagination::ActiveRecordExtension)
7
+ end
@@ -0,0 +1,25 @@
1
+ module CursorPagination
2
+ module ActionViewHelper
3
+ def next_cursor_link(scope, name, params = {}, options = {}, &block)
4
+ url = next_cursor_url(scope, params)
5
+ link_to_unless url.nil?, name, url, options.reverse_merge(:rel => 'next') do
6
+ block.call if block
7
+ end
8
+ end
9
+
10
+ def next_cursor_url(scope, params = {})
11
+ url_for(params.merge(cursor: scope.next_cursor)) unless scope.last_page?
12
+ end
13
+
14
+ def previous_cursor_link(scope, name, params = {}, options = {}, &block)
15
+ url = previous_cursor_url(scope, params)
16
+ link_to_unless url.nil?, name, url, options.reverse_merge(:rel => 'previous') do
17
+ block.call if block
18
+ end
19
+ end
20
+
21
+ def previous_cursor_url(scope, params = {})
22
+ url_for(params.merge(cursor: scope.previous_cursor)) unless scope.first_page?
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,24 @@
1
+ require 'active_support/concern'
2
+ require 'cursor_pagination/active_record_model_extension'
3
+
4
+ module CursorPagination
5
+ module ActiveRecordExtension
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ # Future subclasses will pick up the model extension
10
+ class << self
11
+ def inherited_with_cursor_pagination(kls) #:nodoc:
12
+ inherited_without_cursor_pagination kls
13
+ kls.send(:include, CursorPagination::ActiveRecordModelExtension) if kls.superclass == ActiveRecord::Base
14
+ end
15
+ alias_method_chain :inherited, :cursor_pagination
16
+ end
17
+
18
+ # Existing subclasses pick up the model extension as well
19
+ self.descendants.each do |kls|
20
+ kls.send(:include, CursorPagination::ActiveRecordModelExtension) if kls.superclass == ActiveRecord::Base
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,34 @@
1
+ require 'cursor_pagination/page_scope_methods'
2
+
3
+ module CursorPagination
4
+ module ActiveRecordModelExtension
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ def self.current_cursor
9
+ @current_cursor
10
+ end
11
+
12
+ def self._origin_scope
13
+ @origin_scope
14
+ end
15
+
16
+ def self.cursor_options
17
+ @cursor_options
18
+ end
19
+
20
+ scope :cursor, Proc.new { |cursor, options|
21
+ options = { column: :id, reverse: false }.merge(options || {})
22
+ @current_cursor = cursor
23
+ @origin_scope = self.all
24
+ @cursor_options = options
25
+
26
+ scope = @origin_scope
27
+ scope = scope.where("#{options[:column]} #{options[:reverse] ? '<' : '>'} ?", cursor) if cursor
28
+ scope.limit(25)
29
+ } do
30
+ include CursorPagination::PageScopeMethods
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,36 @@
1
+ module CursorPagination
2
+ module PageScopeMethods
3
+ def per(num)
4
+ limit(num)
5
+ end
6
+
7
+ def first_page?
8
+ previous_cursor == -1
9
+ end
10
+
11
+ def last_page?
12
+ next_cursor == -1
13
+ end
14
+
15
+ def previous_cursor
16
+ options = cursor_options
17
+ result = _origin_scope.where("#{options[:column]} #{options[:reverse] ? '>' : '<'}= ?", current_cursor).limit(limit_value+1).to_a
18
+ case result.size
19
+ when limit_value+1
20
+ result.first.send(options[:column])
21
+ when 0
22
+ -1 #no previous page
23
+ else
24
+ nil #first page, incomplete
25
+ end
26
+
27
+ end
28
+
29
+ def next_cursor
30
+ return -1 if last.nil?
31
+ # try to get something after last cursor
32
+ cursor = last.send(cursor_options[:column])
33
+ _origin_scope.cursor(cursor, cursor_options).per(1).count.zero? ? -1 : cursor
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,3 @@
1
+ module CursorPagination
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,2 @@
1
+ ActiveRecord::Base.configurations = {'test' => {:adapter => 'sqlite3', :database => ':memory:'}}
2
+ ActiveRecord::Base.establish_connection('test')
@@ -0,0 +1,17 @@
1
+ # models
2
+ class Entity < ActiveRecord::Base
3
+
4
+ end
5
+
6
+ #migrations
7
+ class CreateAllTables < ActiveRecord::Migration
8
+ def self.up
9
+ create_table :entities do |t|
10
+ t.integer :custom
11
+ t.timestamps
12
+ end
13
+ end
14
+ end
15
+
16
+ ActiveRecord::Migration.verbose = false
17
+ CreateAllTables.up
@@ -0,0 +1,30 @@
1
+ # require 'rails/all'
2
+ require 'action_controller/railtie'
3
+ require 'action_view/railtie'
4
+
5
+ require 'fake_app/active_record/config' if defined? ActiveRecord
6
+
7
+ # config
8
+ app = Class.new(Rails::Application)
9
+ app.config.secret_token = 'f47a93ac1ff6843777fed92f966d61dc'
10
+ app.config.session_store :cookie_store, :key => '_myapp_session'
11
+ app.config.active_support.deprecation = :log
12
+ app.config.eager_load = false
13
+ # Rais.root
14
+ app.config.root = File.dirname(__FILE__)
15
+ Rails.backtrace_cleaner.remove_silencers!
16
+ app.initialize!
17
+
18
+ # routes
19
+ app.routes.draw do
20
+ resources :entities
21
+ end
22
+
23
+ #models
24
+ require 'fake_app/active_record/models' if defined? ActiveRecord
25
+
26
+ # controllers
27
+ class ApplicationController < ActionController::Base; end
28
+
29
+ # helpers
30
+ Object.const_set(:ApplicationHelper, Module.new)
@@ -0,0 +1,51 @@
1
+ require 'spec_helper'
2
+
3
+ describe CursorPagination::ActionViewHelper do
4
+
5
+ include_context "entities"
6
+
7
+ describe '#previous_cursor_link' do
8
+ context 'having previous pages' do
9
+ context 'the default behaviour' do
10
+ subject { helper.previous_cursor_link second_page, 'Previous', {:controller => 'entities', :action => 'index'} }
11
+ it { should be_a String }
12
+ it { should match(/rel="previous"/) }
13
+ it { should_not match(/cursor=/) }
14
+ end
15
+ context 'the third page' do
16
+ subject { helper.previous_cursor_link third_page, 'Previous', {:controller => 'entities', :action => 'index'} }
17
+ it { should be_a String }
18
+ it { should match(/rel="previous"/) }
19
+ it { should match(/cursor=#{first_entity.id}/) }
20
+ end
21
+ context 'overriding rel=' do
22
+ subject { helper.previous_cursor_link second_page, 'Previous', {:controller => 'entities', :action => 'index'}, {:rel => 'external'} }
23
+ it { should match(/rel="external"/) }
24
+ end
25
+ end
26
+ context 'the first page' do
27
+ subject { helper.previous_cursor_link first_page, 'Previous', {:controller => 'entities', :action => 'index'} }
28
+ it { should be_nil }
29
+ end
30
+ end
31
+
32
+ describe '#next_cursor_link' do
33
+ context 'having more page' do
34
+ context 'the default behaviour' do
35
+ subject { helper.next_cursor_link first_page, 'More', {:controller => 'entities', :action => 'index'} }
36
+ it { should be_a String }
37
+ it { should match(/rel="next"/) }
38
+ it { should match(/cursor=#{first_entity.id}/) }
39
+ end
40
+ context 'overriding rel=' do
41
+ subject { helper.next_cursor_link first_page, 'More', {:controller => 'entities', :action => 'index'}, { :rel => 'external' } }
42
+ it { should match(/rel="external"/) }
43
+ end
44
+ end
45
+ context 'the last page' do
46
+ subject { helper.next_cursor_link last_page, 'More', {:controller => 'entities', :action => 'index'} }
47
+ it { should be_nil }
48
+ end
49
+ end
50
+
51
+ end
@@ -0,0 +1,93 @@
1
+ require 'spec_helper'
2
+
3
+ describe Entity do
4
+
5
+ include_context "entities"
6
+
7
+ specify do
8
+ first_entity.id.should be < second_entity.id
9
+ first_entity.custom.should be > second_entity.custom
10
+ end
11
+
12
+ describe "#cursor method" do
13
+ it "returns first entity only" do
14
+ result = first_page.to_a
15
+ result.size.should eq 1
16
+ result.first.should eq first_entity
17
+ end
18
+
19
+ it "returns second entity only" do
20
+ result = second_page.to_a
21
+ result.size.should eq 1
22
+ result.first.should eq second_entity
23
+ end
24
+
25
+ it "support different orders" do
26
+ result = Entity.order('id DESC').cursor(second_entity.id, reverse: true).per(1).to_a
27
+ result.size.should eq 1
28
+ result.first.should eq first_entity
29
+ end
30
+
31
+ it "support different columns" do
32
+ result = Entity.cursor(second_entity.id, column: :custom).per(1).to_a
33
+ result.size.should eq 1
34
+ result.first.should eq first_entity
35
+ end
36
+
37
+ context "without #per method" do
38
+ before do
39
+ 25.times { Entity.create! }
40
+ end
41
+
42
+ it "returns all Entities" do
43
+ result = Entity.cursor(nil).to_a
44
+ result.size.should eq 25
45
+ end
46
+ end
47
+ end
48
+
49
+ describe "cursor methods" do
50
+ # nil is valid cursor too, it means first page
51
+ # -1 means unavailable cursor (last or first page)
52
+ describe "#next_cursor" do
53
+ ##Default settings
54
+ specify { Entity.cursor(nil).per(10).next_cursor.should eq -1 }
55
+ specify { Entity.cursor(nil).per(10).should be_last_page }
56
+ specify { first_page.next_cursor.should eq first_entity.id}
57
+ specify { first_page.should_not be_last_page}
58
+ specify { last_page.next_cursor.should eq -1 }
59
+
60
+ ##Reverse order
61
+ specify { Entity.order('id DESC').cursor(nil, reverse: true).per(1).next_cursor.should eq last_entity.id }
62
+ specify { Entity.order('id DESC').cursor(second_entity.id, reverse: true).per(1).next_cursor.should eq -1 }
63
+
64
+ ##With custom column
65
+ specify { Entity.order('custom ASC').cursor(second_entity.custom, column: :custom).per(1).next_cursor.should eq -1 }
66
+ specify { Entity.order('custom ASC').cursor(third_entity.custom, column: :custom).per(1).next_cursor.should eq second_entity.custom }
67
+ specify { Entity.order('custom ASC').cursor(nil, column: :custom).per(1).next_cursor.should eq last_entity.custom }
68
+ end
69
+
70
+ describe "#previous_cursor" do
71
+ ##Default settings
72
+ #no previous page
73
+ specify { Entity.cursor(nil).previous_cursor.should eq -1 }
74
+ specify { Entity.cursor(nil).should be_first_page }
75
+ #not full previous page
76
+ specify { Entity.cursor(first_entity.id).previous_cursor.should be_nil }
77
+ specify { Entity.cursor(first_entity.id).should_not be_first_page }
78
+ #full previous page
79
+ specify { third_page.previous_cursor.should eq first_entity.id }
80
+ specify { third_page.should_not be_first_page }
81
+
82
+ ##Reverse order
83
+ specify { Entity.order('id DESC').cursor(nil, reverse: true).previous_cursor.should eq -1 }
84
+ specify { Entity.order('id DESC').cursor(last_entity.id, reverse: true).previous_cursor.should be_nil }
85
+ specify { Entity.order('id DESC').cursor(third_entity.id, reverse: true).per(1).previous_cursor.should eq last_entity.id }
86
+
87
+ ##With custom column
88
+ specify { Entity.order('custom ASC').cursor(nil, column: :custom).previous_cursor.should eq -1 }
89
+ specify { Entity.order('custom ASC').cursor(last_entity.custom, column: :custom).previous_cursor.should be_nil }
90
+ specify { Entity.order('custom ASC').cursor(third_entity.custom, column: :custom).per(1).previous_cursor.should eq last_entity.custom }
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,39 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # Require this file using `require "spec_helper"` to ensure that it is only
4
+ # loaded once.
5
+ require 'active_record'
6
+ require 'cursor_pagination'
7
+
8
+ require 'fake_app/rails'
9
+ require 'rspec/rails'
10
+
11
+ require 'database_cleaner'
12
+
13
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
14
+ #
15
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
16
+ RSpec.configure do |config|
17
+ config.treat_symbols_as_metadata_keys_with_true_values = true
18
+ config.run_all_when_everything_filtered = true
19
+ config.filter_run :focus
20
+
21
+ # Run specs in random order to surface order dependencies. If you find an
22
+ # order dependency and want to debug it, you can fix the order by providing
23
+ # the seed, which is printed after each run.
24
+ # --seed 1234
25
+ config.order = 'random'
26
+
27
+ config.before(:suite) do
28
+ DatabaseCleaner.strategy = :transaction
29
+ DatabaseCleaner.clean_with(:truncation)
30
+ end
31
+
32
+ config.before(:each) do
33
+ DatabaseCleaner.start
34
+ end
35
+
36
+ config.after(:each) do
37
+ DatabaseCleaner.clean
38
+ end
39
+ end
@@ -0,0 +1,16 @@
1
+ shared_context "entities" do
2
+ before do
3
+ 4.times { |n| Entity.create! custom: (4 - n)}
4
+ end
5
+
6
+ let(:entities) { Entity.all.to_a }
7
+ let(:first_entity) { entities.first }
8
+ let(:second_entity) { entities[1] }
9
+ let(:third_entity) { entities[2] }
10
+ let(:last_entity) { entities[3] }
11
+
12
+ let(:first_page) { Entity.cursor(nil).per(1) }
13
+ let(:second_page) { Entity.cursor(first_entity.id).per(1) }
14
+ let(:third_page) { Entity.cursor(second_entity.id).per(1) }
15
+ let(:last_page) { Entity.cursor(third_entity.id).per(1) }
16
+ end
metadata ADDED
@@ -0,0 +1,160 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cursor_pagination
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Sergey Kukunin
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-08-28 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activerecord
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: 3.0.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: 3.0.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec-rails
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: sqlite3-ruby
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: database_cleaner
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - <
60
+ - !ruby/object:Gem::Version
61
+ version: 1.1.1
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - <
67
+ - !ruby/object:Gem::Version
68
+ version: 1.1.1
69
+ - !ruby/object:Gem::Dependency
70
+ name: bundler
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ~>
74
+ - !ruby/object:Gem::Version
75
+ version: '1.3'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ~>
81
+ - !ruby/object:Gem::Version
82
+ version: '1.3'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rake
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description: ActiveRecord plugin for cursor based pagination. Uses some column and
98
+ rpp (results per page) to paginate your content. The main advantage against traditional
99
+ pagination (limmit and offset), that the one URL on specific page will contain the
100
+ data set, despite the newly added entities. It may be useful on the projects, where
101
+ new entities are added often, and specific page now isn't specific page tomorrow.
102
+ email:
103
+ - sergey.kukunin@gmail.com
104
+ executables: []
105
+ extensions: []
106
+ extra_rdoc_files: []
107
+ files:
108
+ - .gitignore
109
+ - .rspec
110
+ - Gemfile
111
+ - LICENSE.txt
112
+ - README.md
113
+ - Rakefile
114
+ - app/helpers/cursor_pagination_helper.rb
115
+ - cursor_pagination.gemspec
116
+ - lib/cursor_pagination.rb
117
+ - lib/cursor_pagination/action_view_helper.rb
118
+ - lib/cursor_pagination/active_record_extension.rb
119
+ - lib/cursor_pagination/active_record_model_extension.rb
120
+ - lib/cursor_pagination/page_scope_methods.rb
121
+ - lib/cursor_pagination/version.rb
122
+ - spec/fake_app/active_record/config.rb
123
+ - spec/fake_app/active_record/models.rb
124
+ - spec/fake_app/rails.rb
125
+ - spec/helpers/cursor_pagination_helper_spec.rb
126
+ - spec/models/entity_spec.rb
127
+ - spec/spec_helper.rb
128
+ - spec/support/spec_shared.rb
129
+ homepage: https://github.com/Kukunin/cursor_pagination
130
+ licenses:
131
+ - MIT
132
+ metadata: {}
133
+ post_install_message:
134
+ rdoc_options: []
135
+ require_paths:
136
+ - lib
137
+ required_ruby_version: !ruby/object:Gem::Requirement
138
+ requirements:
139
+ - - '>='
140
+ - !ruby/object:Gem::Version
141
+ version: '0'
142
+ required_rubygems_version: !ruby/object:Gem::Requirement
143
+ requirements:
144
+ - - '>='
145
+ - !ruby/object:Gem::Version
146
+ version: '0'
147
+ requirements: []
148
+ rubyforge_project:
149
+ rubygems_version: 2.0.3
150
+ signing_key:
151
+ specification_version: 4
152
+ summary: ActiveRecord plugin for cursor based pagination
153
+ test_files:
154
+ - spec/fake_app/active_record/config.rb
155
+ - spec/fake_app/active_record/models.rb
156
+ - spec/fake_app/rails.rb
157
+ - spec/helpers/cursor_pagination_helper_spec.rb
158
+ - spec/models/entity_spec.rb
159
+ - spec/spec_helper.rb
160
+ - spec/support/spec_shared.rb