wor-paginate 0.1.0

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: d84187f4c6aefe0057da92521b232708da407df2
4
+ data.tar.gz: af3d77d7ed94db88542c07ad90649207dacbe804
5
+ SHA512:
6
+ metadata.gz: 9b9a8636267edd5501e0f9f685c08a3d9ccf1342facdb0b6cc9d6beb7da7e0e0daf75acd248f32736ad841eabc754a4f5d7259d029ca20f7a0f3be7cc2f08d0b
7
+ data.tar.gz: 264eedc255fbaab4cbc28e4d9911eb3dd2713469ce82bdcdd7f1ca7a4fdd6d4157e327ae95eed69283ff2f7ba57171d2829e0628612e93872bf3831a8b604370
data/.gitignore ADDED
@@ -0,0 +1,331 @@
1
+ spec/dummy/db/*.sqlite3
2
+ spec/dummy/db/*.sqlite3-journal
3
+ spec/dummy/log/*.log
4
+ spec/dummy/tmp/
5
+
6
+ /.bundle/
7
+ /.yardoc
8
+ /Gemfile.lock
9
+ /_yardoc/
10
+ /coverage/
11
+ /doc/
12
+ /pkg/
13
+ /spec/reports/
14
+ /tmp/
15
+ *.gem
16
+
17
+ # Created by https://www.gitignore.io/api/ruby,rubymine,rails,emacs,vim,sublimetext,osx,macos,linux,windows
18
+
19
+ ### Emacs ###
20
+ # -*- mode: gitignore; -*-
21
+ *~
22
+ \#*\#
23
+ /.emacs.desktop
24
+ /.emacs.desktop.lock
25
+ *.elc
26
+ auto-save-list
27
+ tramp
28
+ .\#*
29
+
30
+ # Org-mode
31
+ .org-id-locations
32
+ *_archive
33
+
34
+ # flymake-mode
35
+ *_flymake.*
36
+
37
+ # eshell files
38
+ /eshell/history
39
+ /eshell/lastdir
40
+
41
+ # elpa packages
42
+ /elpa/
43
+
44
+ # reftex files
45
+ *.rel
46
+
47
+ # AUCTeX auto folder
48
+ /auto/
49
+
50
+ # cask packages
51
+ .cask/
52
+ dist/
53
+
54
+ # Flycheck
55
+ flycheck_*.el
56
+
57
+ # server auth directory
58
+ /server/
59
+
60
+ # projectiles files
61
+ .projectile
62
+
63
+ # directory configuration
64
+ .dir-locals.el
65
+
66
+ ### Linux ###
67
+
68
+ # temporary files which can be created if a process still has a handle open of a deleted file
69
+ .fuse_hidden*
70
+
71
+ # KDE directory preferences
72
+ .directory
73
+
74
+ # Linux trash folder which might appear on any partition or disk
75
+ .Trash-*
76
+
77
+ # .nfs files are created when an open file is removed but is still being accessed
78
+ .nfs*
79
+
80
+ ### macOS ###
81
+ *.DS_Store
82
+ .AppleDouble
83
+ .LSOverride
84
+
85
+ # Icon must end with two \r
86
+ Icon
87
+
88
+
89
+ # Thumbnails
90
+ ._*
91
+
92
+ # Files that might appear in the root of a volume
93
+ .DocumentRevisions-V100
94
+ .fseventsd
95
+ .Spotlight-V100
96
+ .TemporaryItems
97
+ .Trashes
98
+ .VolumeIcon.icns
99
+ .com.apple.timemachine.donotpresent
100
+
101
+ # Directories potentially created on remote AFP share
102
+ .AppleDB
103
+ .AppleDesktop
104
+ Network Trash Folder
105
+ Temporary Items
106
+ .apdisk
107
+
108
+ ### OSX ###
109
+
110
+ # Icon must end with two \r
111
+
112
+
113
+ # Thumbnails
114
+
115
+ # Files that might appear in the root of a volume
116
+
117
+ # Directories potentially created on remote AFP share
118
+
119
+ ### Rails ###
120
+ *.rbc
121
+ capybara-*.html
122
+ .rspec
123
+ /log
124
+ /tmp
125
+ /db/*.sqlite3
126
+ /db/*.sqlite3-journal
127
+ /public/system
128
+ /coverage/
129
+ /spec/tmp
130
+ **.orig
131
+ rerun.txt
132
+ pickle-email-*.html
133
+
134
+ # TODO Comment out this rule if you are OK with secrets being uploaded to the repo
135
+ config/initializers/secret_token.rb
136
+
137
+ # Only include if you have production secrets in this file, which is no longer a Rails default
138
+ # config/secrets.yml
139
+
140
+ # dotenv
141
+ # TODO Comment out this rule if environment variables can be committed
142
+ .env
143
+
144
+ ## Environment normalization:
145
+ /.bundle
146
+ /vendor/bundle
147
+
148
+ # these should all be checked in to normalize the environment:
149
+ # Gemfile.lock, .ruby-version, .ruby-gemset
150
+
151
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
152
+ .rvmrc
153
+
154
+ # if using bower-rails ignore default bower_components path bower.json files
155
+ /vendor/assets/bower_components
156
+ *.bowerrc
157
+ bower.json
158
+
159
+ # Ignore pow environment settings
160
+ .powenv
161
+
162
+ # Ignore Byebug command history file.
163
+ .byebug_history
164
+
165
+ ### Ruby ###
166
+ *.gem
167
+ /.config
168
+ /InstalledFiles
169
+ /pkg/
170
+ /spec/reports/
171
+ /spec/examples.txt
172
+ /test/tmp/
173
+ /test/version_tmp/
174
+ /tmp/
175
+
176
+ # Used by dotenv library to load environment variables.
177
+ # .env
178
+
179
+ ## Specific to RubyMotion:
180
+ .dat*
181
+ .repl_history
182
+ build/
183
+ *.bridgesupport
184
+ build-iPhoneOS/
185
+ build-iPhoneSimulator/
186
+
187
+ ## Specific to RubyMotion (use of CocoaPods):
188
+ #
189
+ # We recommend against adding the Pods directory to your .gitignore. However
190
+ # you should judge for yourself, the pros and cons are mentioned at:
191
+ # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
192
+ #
193
+ # vendor/Pods/
194
+
195
+ ## Documentation cache and generated files:
196
+ /.yardoc/
197
+ /_yardoc/
198
+ /doc/
199
+ /rdoc/
200
+
201
+ ## Environment normalization:
202
+ /.bundle/
203
+ /lib/bundler/man/
204
+
205
+ # for a library or gem, you might want to ignore these files since the code is
206
+ # intended to run in multiple environments; otherwise, check them in:
207
+ # Gemfile.lock
208
+ # .ruby-version
209
+ # .ruby-gemset
210
+
211
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
212
+
213
+ ### RubyMine ###
214
+ # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
215
+ # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
216
+
217
+ # User-specific stuff:
218
+ .idea/**/workspace.xml
219
+ .idea/**/tasks.xml
220
+
221
+ # Sensitive or high-churn files:
222
+ .idea/**/dataSources/
223
+ .idea/**/dataSources.ids
224
+ .idea/**/dataSources.xml
225
+ .idea/**/dataSources.local.xml
226
+ .idea/**/sqlDataSources.xml
227
+ .idea/**/dynamic.xml
228
+ .idea/**/uiDesigner.xml
229
+
230
+ # Gradle:
231
+ .idea/**/gradle.xml
232
+ .idea/**/libraries
233
+
234
+ # Mongo Explorer plugin:
235
+ .idea/**/mongoSettings.xml
236
+
237
+ ## File-based project format:
238
+ *.iws
239
+
240
+ ## Plugin-specific files:
241
+
242
+ # IntelliJ
243
+ /out/
244
+
245
+ # mpeltonen/sbt-idea plugin
246
+ .idea_modules/
247
+
248
+ # JIRA plugin
249
+ atlassian-ide-plugin.xml
250
+
251
+ # Crashlytics plugin (for Android Studio and IntelliJ)
252
+ com_crashlytics_export_strings.xml
253
+ crashlytics.properties
254
+ crashlytics-build.properties
255
+ fabric.properties
256
+
257
+ ### RubyMine Patch ###
258
+ # Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
259
+
260
+ # *.iml
261
+ # modules.xml
262
+ # .idea/misc.xml
263
+ # *.ipr
264
+
265
+ ### SublimeText ###
266
+ # cache files for sublime text
267
+ *.tmlanguage.cache
268
+ *.tmPreferences.cache
269
+ *.stTheme.cache
270
+
271
+ # workspace files are user-specific
272
+ *.sublime-workspace
273
+
274
+ # project files should be checked into the repository, unless a significant
275
+ # proportion of contributors will probably not be using SublimeText
276
+ # *.sublime-project
277
+
278
+ # sftp configuration file
279
+ sftp-config.json
280
+
281
+ # Package control specific files
282
+ Package Control.last-run
283
+ Package Control.ca-list
284
+ Package Control.ca-bundle
285
+ Package Control.system-ca-bundle
286
+ Package Control.cache/
287
+ Package Control.ca-certs/
288
+ Package Control.merged-ca-bundle
289
+ Package Control.user-ca-bundle
290
+ oscrypto-ca-bundle.crt
291
+ bh_unicode_properties.cache
292
+
293
+ # Sublime-github package stores a github token in this file
294
+ # https://packagecontrol.io/packages/sublime-github
295
+ GitHub.sublime-settings
296
+
297
+ ### Vim ###
298
+ # swap
299
+ [._]*.s[a-v][a-z]
300
+ [._]*.sw[a-p]
301
+ [._]s[a-v][a-z]
302
+ [._]sw[a-p]
303
+ # session
304
+ Session.vim
305
+ # temporary
306
+ .netrwhist
307
+ # auto-generated tag files
308
+ tags
309
+
310
+ ### Windows ###
311
+ # Windows thumbnail cache files
312
+ Thumbs.db
313
+ ehthumbs.db
314
+ ehthumbs_vista.db
315
+
316
+ # Folder config file
317
+ Desktop.ini
318
+
319
+ # Recycle Bin used on file shares
320
+ $RECYCLE.BIN/
321
+
322
+ # Windows Installer files
323
+ *.cab
324
+ *.msi
325
+ *.msm
326
+ *.msp
327
+
328
+ # Windows shortcuts
329
+ *.lnk
330
+
331
+ # End of https://www.gitignore.io/api/ruby,rubymine,rails,emacs,vim,sublimetext,osx,macos,linux,windows
data/.rubocop.yml ADDED
@@ -0,0 +1,52 @@
1
+ AllCops:
2
+ Exclude:
3
+ - wor-paginate.gemspec
4
+ - spec/spy.rb
5
+ - spec/dummy/db/**/*
6
+ - spec/dummy/config/**/*
7
+ - spec/spec_helper.rb
8
+
9
+ Documentation:
10
+ Enabled: false
11
+
12
+ LineLength:
13
+ Max: 99
14
+
15
+ FrozenStringLiteralComment:
16
+ Enabled: false
17
+
18
+ Metrics/BlockLength:
19
+ Enabled: true
20
+ Exclude:
21
+ - spec/**/*
22
+
23
+ # rubocop-rspec custom configurations
24
+
25
+ require: rubocop-rspec
26
+
27
+ Style/VariableNumber:
28
+ EnforcedStyle: snake_case
29
+
30
+ RSpec/ExampleLength:
31
+ Enabled: false
32
+
33
+ RSpec/AnyInstance:
34
+ Enabled: false
35
+
36
+ RSpec/MultipleExpectations:
37
+ Enabled: false
38
+
39
+ RSpec/NestedGroups:
40
+ Max: 5
41
+
42
+ Lint/AmbiguousBlockAssociation:
43
+ Enabled: false
44
+
45
+ RSpec/LetSetup:
46
+ Enabled: false
47
+
48
+ RSpec/FilePath:
49
+ Exclude:
50
+ - spec/dummy_controller_without_gems_spec.rb
51
+ - spec/matchers_spec.rb
52
+ - spec/dummy_controller_spec.rb
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.3.1
data/.travis.yml ADDED
@@ -0,0 +1,15 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2.2
4
+ - 2.3.3
5
+ - 2.4.0
6
+
7
+ install:
8
+ - gem install bundler
9
+ - bundle install --retry=3
10
+ - bundle exec rake db:migrate RAILS_ENV=test -f spec/dummy/Rakefile
11
+
12
+ script:
13
+ - bundle exec rubocop --format simple
14
+ - bundle exec rspec
15
+ - bundle exec codeclimate-test-reporter
data/CHANGELOG.md ADDED
@@ -0,0 +1,2 @@
1
+
2
+ ## Change log
data/Gemfile ADDED
@@ -0,0 +1,35 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Declare your gem's dependencies in wor-paginate.gemspec.
4
+ # Bundler will treat runtime dependencies like base dependencies, and
5
+ # development dependencies will be added by default to the :development group.
6
+ gemspec
7
+
8
+ # Declare any dependencies that are still in development here instead of in
9
+ # your gemspec. These might include edge Rails or gems from your path or
10
+ # Git. Remember to move these dependencies to your gemspec before releasing
11
+ # your gem to rubygems.org.
12
+
13
+ # To use a debugger
14
+ # gem 'byebug', group: [:development, :test]
15
+
16
+ group :development, :test do
17
+ gem 'active_model_serializers', '~> 0.10.0'
18
+ gem 'bundler', '~> 1.13'
19
+ gem 'byebug', '~> 9.0'
20
+ gem 'codeclimate-test-reporter', '~> 1.0.0'
21
+ gem 'database_cleaner', '~> 1.5.0'
22
+ gem 'factory_girl_rails', '~> 4.7.0'
23
+ gem 'faker', '~> 1.7.0'
24
+ gem 'generator_spec', '~> 0.9.0'
25
+ gem 'kaminari', '~> 0.17.0'
26
+ gem 'rake', '~> 10.0'
27
+ gem 'rspec', '~> 3.0'
28
+ gem 'rspec-rails', '~> 3.6.0'
29
+ gem 'rubocop', '~> 0.49.1'
30
+ gem 'rubocop-rspec', '~> 1.15.0'
31
+ gem 'simplecov', '~> 0.13.0'
32
+ gem 'sqlite3', '~> 1.3.0'
33
+ gem 'webmock', '~> 3.0.0'
34
+ gem 'will_paginate', '~> 3.1.0'
35
+ end
data/LICENSE.md ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 Wolox
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,181 @@
1
+ # Wor::Paginate
2
+ [![Build Status](https://travis-ci.org/Wolox/wor-requests.svg)](https://travis-ci.org/Wolox/wor-paginate)
3
+ [![Gem Version](https://badge.fury.io/rb/wor-paginate.svg)](https://badge.fury.io/rb/wor-paginate)
4
+ [![Dependency Status](https://gemnasium.com/badges/github.com/Wolox/wor-paginate.svg)](https://gemnasium.com/github.com/Wolox/wor-paginate)
5
+ [![Code Climate](https://codeclimate.com/github/Wolox/wor-paginate/badges/gpa.svg)](https://codeclimate.com/github/Wolox/wor-paginate)
6
+ [![Test Coverage](https://codeclimate.com/github/Wolox/wor-paginate/badges/coverage.svg)](https://codeclimate.com/github/Wolox/wor-paginate/coverage)
7
+
8
+ Wor::Paginate is a gem for Rails that simplifies pagination, particularly for controller methods, while standardizing JSON output for APIs. It's meant to work both as a standalone pagination gem and as an extra layer over [Kaminari](https://github.com/kaminari/kaminari) and [will_paginate](https://github.com/mislav/will_paginate).
9
+
10
+ ## Installation
11
+ Add the following line to your application's Gemfile:
12
+
13
+ ```ruby
14
+ gem 'wor-paginate'
15
+ ```
16
+
17
+ And then execute:
18
+ ```bash
19
+ $ bundle
20
+ ```
21
+
22
+ Or install it yourself as:
23
+ ```bash
24
+ $ gem install wor-paginate
25
+ ```
26
+
27
+ Then you can run `rails generate wor:paginate:install` to create the initializer for configuration details, including default formatter class, page and limit params and default page number.
28
+
29
+ ## Usage
30
+ ### Basic usage
31
+ The basic use case is to paginate using default values. This is achieved by including the module in a controller and calling render_paginate in the method that needs pagination.
32
+ ```ruby
33
+ class DummyModelsController < ApplicationController
34
+ include Wor::Paginate
35
+
36
+ def index
37
+ render_paginated DummyModel
38
+ end
39
+ end
40
+ ```
41
+ The first parameter to render_paginated can be multiple things:
42
+ * ActiveRecord/ActiveRecord::Relation
43
+ * Enumerables (for example, arrays and ranges)
44
+ * Pre-paginated Kaminari or will_paginate relations (original pagination will be ignored)
45
+
46
+ The response to the index will then be:
47
+ ```json
48
+ {
49
+ "items": [
50
+ {
51
+ "id": 1,
52
+ "name": "1c",
53
+ "something": 27
54
+ },
55
+ {
56
+ "id": 2,
57
+ "name": "i",
58
+ "something": 68
59
+ },
60
+ ...
61
+ {
62
+ "id": 25,
63
+ "name": "2m",
64
+ "something": 32
65
+ }
66
+ ],
67
+ "count": 25,
68
+ "total_pages": 2,
69
+ "total_count": 28,
70
+ "current_page": 1,
71
+
72
+ }
73
+ ```
74
+
75
+ Page number is passed through the `page` option of the `render_paginated` method. If none is supplied, `params[:page]` will be used, (or the default parameter configured in the initializer).
76
+ By default, if the page parameter is not present we will use 1 as the page (or the default `page` parameter configured in the initializer).
77
+ The amount of items is passed through the `limit` option of the `render_paginated` method. If none is supplied, `params[:limit]` will be used (or the default parameter configured in the initializer). Default is 25.
78
+ The default serializer and formatter will be used.
79
+
80
+ ### Customizing output
81
+ #### Custom serializers
82
+ A custom serializer for each object can be passed using the `each_serializer` option:
83
+ ```ruby
84
+ render_paginated DummyModel, each_serializer: CustomDummyModelSerializer
85
+ ```
86
+ where the serializer is just an [`ActiveModel::Serializer`](https://github.com/rails-api/active_model_serializers).
87
+
88
+ #### Custom formatters
89
+ A formatter is an object that defines the output of the render_paginated method. In case the application needs a different format for a request, it can be passed to the `render_paginated` method using the `formatter` option:
90
+ ```ruby
91
+ render_paginated DummyModel, formatter: CustomFormatter
92
+ ```
93
+ or it can also be set as a default in the initializer.
94
+
95
+ A new formatter can be created inheriting from the default one. The `format` method should be redefined returning something that can be converted to json.
96
+
97
+ ```ruby
98
+ class CustomFormatter < Wor::Paginate::Formatter
99
+ def format
100
+ { page: serialized_content, current: current_page }
101
+ end
102
+ end
103
+ ```
104
+
105
+ Available helper methods are:
106
+ * `current_page`: integer with the current page
107
+ * `count`: number of items in the page (post-pagination)
108
+ * `total_count`: number of total items (pre-pagination)
109
+ * `total_pages`: number of pages given the current limit (post-pagination)
110
+ * `paginated_content`: its class depends on the original content passed to render_paginated, it's the paginated but not yet serialized content.
111
+ * `serialized_content`: array with all the items after going through the serializer (either the default or a supplied one)
112
+
113
+ ### Working with Kaminari or will_paginate
114
+ If either Kaminari or will_paginate are required in the project, Wor::Paginate will use them for pagination with no code or configuration change.
115
+
116
+ ### Test helpers
117
+ You can use the `be_paginated` matcher to test your endpoints. It also accepts the `with` chain method to receive a formatter.
118
+
119
+ You only need to add this in your spec_helper.rb (or rails_helper.rb)
120
+ ```
121
+ # spec/spec_helper.rb
122
+ require 'wor/paginate/rspec'
123
+ ```
124
+ And in your spec do
125
+ ```
126
+ # spec/controllers/your_controller.rb
127
+ describe YourController do
128
+ describe '#index' do
129
+ it 'checks that the response keys matches with the default formatter' do
130
+ get :index
131
+ expect(response_body(response)).to be_paginated
132
+ end
133
+ end
134
+
135
+ describe '#index_with_custom_formatter' do
136
+ it 'checks that the response keys matches with the custom formatter' do
137
+ get :index_custom_formatter
138
+ expect(response_body(response)).to be_paginated.with(CustomFormatter)
139
+ end
140
+ end
141
+ end
142
+ ```
143
+
144
+ ## Contributing
145
+
146
+ 1. Fork it
147
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
148
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
149
+ 4. Run rubocop lint (`bundle exec rubocop -R --format simple`)
150
+ 5. Run rspec tests (`bundle exec rspec`)
151
+ 6. Push your branch (`git push origin my-new-feature`)
152
+ 7. Create a new Pull Request
153
+
154
+ ## About ##
155
+
156
+ This project is maintained by [Hugo Farji](https://github.com/hdf1986), [Ignacio Coluccio](https://github.com/icoluccio), and [Alan Halatian](https://github.com/alanhala). It was written by [Wolox](http://www.wolox.com.ar).
157
+ ![Wolox](https://raw.githubusercontent.com/Wolox/press-kit/master/logos/logo_banner.png)
158
+
159
+ ## License
160
+
161
+ **wor-paginate** is available under the MIT [license](https://raw.githubusercontent.com/Wolox/wor-paginate/master/LICENSE.md).
162
+
163
+ Copyright (c) 2017 Wolox
164
+
165
+ Permission is hereby granted, free of charge, to any person obtaining a copy
166
+ of this software and associated documentation files (the "Software"), to deal
167
+ in the Software without restriction, including without limitation the rights
168
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
169
+ copies of the Software, and to permit persons to whom the Software is
170
+ furnished to do so, subject to the following conditions:
171
+
172
+ The above copyright notice and this permission notice shall be included in
173
+ all copies or substantial portions of the Software.
174
+
175
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
176
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
177
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
178
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
179
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
180
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
181
+ THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task default: :spec
@@ -0,0 +1,13 @@
1
+ Wor::Paginate.configure do |config|
2
+ config.default_per_page = 25
3
+ # config.default_page = 1
4
+
5
+ config.page_param = :page
6
+ config.per_page_param = :per
7
+
8
+ # In case you want to use other format for your response, you can override our formatter here
9
+ # You can extend from Wor::Paginate::Formatter and override the 'format' method
10
+ # For more info about available methods for formatters see:
11
+ # https://github.com/Wolox/wor-paginate/blob/master/lib/wor/paginate/formatter.rb
12
+ # config.formatter = Wor::Paginate::Formatter
13
+ end
@@ -0,0 +1,14 @@
1
+ module Wor
2
+ module Paginate
3
+ module Generators
4
+ class InstallGenerator < Rails::Generators::Base
5
+ source_root File.expand_path('../../../templates', __FILE__)
6
+ desc 'Creates Wor-Paginate initializer for your application'
7
+
8
+ def copy_initializer
9
+ template 'wor_paginate.rb', 'config/initializers/wor_paginate.rb'
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,21 @@
1
+ require_relative 'paginate/adapters/base'
2
+ require_relative 'paginate/adapters/active_record'
3
+ require_relative 'paginate/adapters/enumerable'
4
+ require_relative 'paginate/adapters/kaminari'
5
+ require_relative 'paginate/adapters/will_paginate'
6
+ require_relative 'paginate/adapters/kaminari_already_paginated'
7
+ require_relative 'paginate/adapters/will_paginate_already_paginated'
8
+ require_relative 'paginate/exceptions/no_pagination_adapter'
9
+ require_relative 'paginate/exceptions/invalid_page_number'
10
+ require_relative 'paginate/exceptions/invalid_limit_number'
11
+ require_relative 'paginate/formatter'
12
+ require_relative 'paginate/config'
13
+ require_relative 'paginate/paginate'
14
+
15
+ module Wor
16
+ module Paginate
17
+ def self.configure
18
+ yield Config
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,37 @@
1
+ # Used when render_paginated is called with an ActiveRecord directly, without a
2
+ # pagination gem like kaminari or will_paginate
3
+ ### render_paginated DummyModel
4
+ module Wor
5
+ module Paginate
6
+ module Adapters
7
+ class ActiveRecord < Base
8
+ attr_reader :page
9
+
10
+ def required_methods
11
+ %i[offset limit table_name]
12
+ end
13
+
14
+ def paginated_content
15
+ @paginated_content ||= @content.offset(offset).limit(@limit)
16
+ end
17
+
18
+ delegate :count, to: :paginated_content
19
+
20
+ def total_count
21
+ @content.count
22
+ end
23
+
24
+ def total_pages
25
+ (total_count.to_f / @limit.to_f).ceil
26
+ end
27
+
28
+ private
29
+
30
+ def offset
31
+ return 0 if @page.zero?
32
+ (@page - 1) * @limit
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,32 @@
1
+ module Wor
2
+ module Paginate
3
+ module Adapters
4
+ class Base
5
+ attr_reader :page
6
+
7
+ def initialize(content, page, limit)
8
+ @content = content
9
+ @page = page.to_i
10
+ @limit = limit.to_i
11
+ raise Wor::Paginate::Exceptions::InvalidPageNumber if @page <= 0
12
+ raise Wor::Paginate::Exceptions::InvalidLimitNumber if @limit <= 0
13
+ end
14
+
15
+ def adapt?
16
+ required_methods.all? { |method| @content.respond_to? method }
17
+ end
18
+
19
+ %i[required_methods paginated_content count total_count next_page].each do |method|
20
+ define_method(method) { raise NotImplementedError }
21
+ end
22
+
23
+ delegate :total_pages, to: :paginated_content
24
+
25
+ def next_page
26
+ return nil if page >= total_pages
27
+ page + 1
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,31 @@
1
+ # Used when render_paginated is called with an Enumerable, something like
2
+ ### render_paginated [1,2,3,4]
3
+ module Wor
4
+ module Paginate
5
+ module Adapters
6
+ class Enumerable < Base
7
+ attr_reader :page
8
+
9
+ def required_methods
10
+ %i[to_a]
11
+ end
12
+
13
+ def paginated_content
14
+ return @paginated_content if @paginated_content
15
+ content_array = @content.to_a
16
+ @paginated_content = content_array.slice((page - 1) * @limit, @limit)
17
+ end
18
+
19
+ delegate :count, to: :paginated_content
20
+
21
+ def total_count
22
+ @content.count
23
+ end
24
+
25
+ def total_pages
26
+ (total_count / @limit.to_f).ceil
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,20 @@
1
+ # Used when render_paginated is called with an ActiveModel directly, with kaminari
2
+ # already required. Something like
3
+ ### render_paginated DummyModel
4
+ module Wor
5
+ module Paginate
6
+ module Adapters
7
+ class Kaminari < Base
8
+ def required_methods
9
+ %i[page]
10
+ end
11
+
12
+ def paginated_content
13
+ @paginated_content ||= @content.page(@page).per(@limit)
14
+ end
15
+
16
+ delegate :count, :total_count, :total_pages, :next_page, to: :paginated_content
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,32 @@
1
+ # Used when render_paginated is called with an already paginated ActiveModel with kaminari
2
+ ### render_paginated DummyModel.page
3
+ module Wor
4
+ module Paginate
5
+ module Adapters
6
+ class KaminariAlreadyPaginated < Base
7
+ def required_methods
8
+ # Methods Kaminari adds to ActiveRecord relations:
9
+ ### [:padding, :per, :total_pages, :num_pages, :current_page, :first_page?,
10
+ ### :prev_page, :last_page?, :next_page, :out_of_range?, :total_count, :entry_name]
11
+ %i[padding total_count num_pages current_page prev_page]
12
+ end
13
+
14
+ def paginated_content
15
+ @paginated_content ||= @content.page(@page).per(@limit)
16
+ end
17
+
18
+ def count
19
+ @content.count
20
+ end
21
+
22
+ def total_count
23
+ @content.total_count
24
+ end
25
+
26
+ def total_pages
27
+ @content.total_pages
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,30 @@
1
+ # Used when render_paginated is called with an ActiveModel directly, with will_paginate
2
+ # already required. Something like
3
+ ### render_paginated DummyModel
4
+ module Wor
5
+ module Paginate
6
+ module Adapters
7
+ class WillPaginate < Base
8
+ attr_reader :page
9
+
10
+ def required_methods
11
+ %i[paginate]
12
+ end
13
+
14
+ def paginated_content
15
+ @paginated_content ||= @content.paginate(page: @page, per_page: @limit)
16
+ end
17
+
18
+ def count
19
+ paginated_content.to_a.size
20
+ end
21
+
22
+ def total_count
23
+ paginated_content.count
24
+ end
25
+
26
+ delegate :total_pages, :next_page, to: :paginated_content
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,32 @@
1
+ # Used when render_paginated is called with an already paginated ActiveModel with will_paginate
2
+ ### render_paginated DummyModel.paginate(page: 1)
3
+
4
+ module Wor
5
+ module Paginate
6
+ module Adapters
7
+ class WillPaginateAlreadyPaginated < Base
8
+ attr_reader :page
9
+
10
+ def required_methods
11
+ # Methods will_paginate adds to ActiveRecord relations:
12
+ ### [:current_page, :total_entries, :total_entries=, :find_last, :current_page=,
13
+ ### :scoped, :total_pages, :next_page, :previous_page, :out_of_bounds?]
14
+ %i[previous_page out_of_bounds? total_entries= total_pages current_page=]
15
+ end
16
+
17
+ def paginated_content
18
+ @paginated_content ||= @content.limit(nil).offset(0)
19
+ .paginate(page: @page, per_page: @limit)
20
+ end
21
+
22
+ def count
23
+ paginated_content.to_a.size
24
+ end
25
+
26
+ def total_count
27
+ paginated_content.total_entries
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,31 @@
1
+ module Wor
2
+ module Paginate
3
+ module Config
4
+ DEFAULTS_CONFIGS = {
5
+ default_per_page: 25,
6
+ default_page: 1,
7
+ page_param: :page,
8
+ per_page_param: :per_page,
9
+ formatter: Wor::Paginate::Formatter,
10
+ max_limit: 50
11
+ }.freeze
12
+
13
+ module_function
14
+
15
+ DEFAULTS_CONFIGS.each do |key, value|
16
+ define_method key do
17
+ instance_variable_get("@#{key}") || instance_variable_set("@#{key}", value)
18
+ end
19
+
20
+ define_method "#{key}=" do |v|
21
+ instance_variable_set("@#{key}", v)
22
+ end
23
+ end
24
+
25
+ # This is mostly useful for the tests
26
+ def reset!
27
+ DEFAULTS_CONFIGS.each { |k, v| send("#{k}=", v) }
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,8 @@
1
+ module Wor
2
+ module Paginate
3
+ module Exceptions
4
+ class InvalidLimitNumber < StandardError
5
+ end
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ module Wor
2
+ module Paginate
3
+ module Exceptions
4
+ class InvalidPageNumber < StandardError
5
+ end
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ module Wor
2
+ module Paginate
3
+ module Exceptions
4
+ class NoPaginationAdapter < StandardError
5
+ end
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,44 @@
1
+ module Wor
2
+ module Paginate
3
+ class Formatter
4
+ attr_accessor :adapter, :content, :formatter, :options
5
+
6
+ def initialize(adapter, options = {})
7
+ @adapter = adapter
8
+ @options = options
9
+ end
10
+
11
+ def format
12
+ {
13
+ page: serialized_content,
14
+ count: count,
15
+ total_pages: total_pages,
16
+ total_count: total_count,
17
+ current_page: current_page,
18
+ next_page: next_page
19
+ }
20
+ end
21
+
22
+ protected
23
+
24
+ delegate :count, :total_count, :total_pages, :next_page, to: :adapter
25
+
26
+ def current_page
27
+ adapter.page.to_i
28
+ end
29
+
30
+ def paginated_content
31
+ @content ||= adapter.paginated_content
32
+ end
33
+
34
+ def serialized_content
35
+ return paginated_content.as_json if serializer.blank?
36
+ paginated_content.map { |item| serializer.new(item) }
37
+ end
38
+
39
+ def serializer
40
+ options[:each_serializer]
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,52 @@
1
+ module Wor
2
+ module Paginate
3
+ # The order of this array is important!
4
+ # In a future release we'll provide an interface to manipulate it
5
+ ADAPTERS = [
6
+ Adapters::KaminariAlreadyPaginated,
7
+ Adapters::WillPaginateAlreadyPaginated,
8
+ Adapters::WillPaginate,
9
+ Adapters::Kaminari,
10
+ Adapters::ActiveRecord,
11
+ Adapters::Enumerable
12
+ ].freeze
13
+
14
+ def render_paginated(content, options = {})
15
+ render json: paginate(content, options)
16
+ end
17
+
18
+ def paginate(content, options = {})
19
+ adapter = find_adapter_for_content(content, options)
20
+ raise Exceptions::NoPaginationAdapter if adapter.blank?
21
+ formatter_class(options).new(adapter, options).format
22
+ end
23
+
24
+ def formatter_class(options)
25
+ options[:formatter].presence || Formatter
26
+ end
27
+
28
+ def find_adapter_for_content(content, options)
29
+ ADAPTERS.map { |adapter| adapter.new(content, page(options), limit(options)) }
30
+ .find(&:adapt?)
31
+ end
32
+
33
+ def page(options)
34
+ options[:page] || params[Config.page_param] || Config.default_page
35
+ end
36
+
37
+ def option_limit(options)
38
+ options[:limit].to_i unless options[:limit].nil?
39
+ end
40
+
41
+ def param_limit
42
+ params[Config.per_page_param].to_i unless params[Config.per_page_param].nil?
43
+ end
44
+
45
+ def limit(options)
46
+ [
47
+ Config.max_limit,
48
+ option_limit(options) || param_limit || Config.default_per_page
49
+ ].min
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,47 @@
1
+ class MockedAdapter < Wor::Paginate::Adapters::Base
2
+ def initialize; end
3
+
4
+ def count
5
+ 3
6
+ end
7
+
8
+ def total_count
9
+ 5
10
+ end
11
+
12
+ def total_pages
13
+ 10
14
+ end
15
+
16
+ def next_page
17
+ 2
18
+ end
19
+
20
+ def page
21
+ 1
22
+ end
23
+
24
+ def paginated_content
25
+ []
26
+ end
27
+ end
28
+
29
+ RSpec::Matchers.define :be_paginated do
30
+ match do |actual_response|
31
+ formatter = @custom_formatter || Wor::Paginate::Formatter
32
+ @formatted_keys = formatter.new(MockedAdapter.new).format.as_json.keys
33
+ actual_response.keys == @formatted_keys
34
+ end
35
+
36
+ chain :with do |custom_formatter|
37
+ @custom_formatter = custom_formatter
38
+ end
39
+
40
+ failure_message do |actual_response|
41
+ "expected that #{actual_response} to be paginated with keys #{@formatted_keys}"
42
+ end
43
+
44
+ failure_message_when_negated do |actual_response|
45
+ "expected that #{actual_response} not to be paginated with keys #{@formatted_keys}"
46
+ end
47
+ end
@@ -0,0 +1,5 @@
1
+ module Wor
2
+ module Paginate
3
+ VERSION = '0.1.0'.freeze
4
+ end
5
+ end
@@ -0,0 +1,24 @@
1
+ lib = File.expand_path('../lib', __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require "wor/paginate/version"
4
+ require 'date'
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "wor-paginate"
8
+ s.version = Wor::Paginate::VERSION
9
+ s.platform = Gem::Platform::RUBY
10
+ s.date = Date.today
11
+ s.authors = ["hdf1986", "icoluccio", "alanhala"]
12
+ s.email = ["hugo.farji@wolox.com.ar", "ignacio.coluccio@wolox.com.ar", "alan.halatian@wolox.com.ar"]
13
+ s.homepage = "https://github.com/Wolox/wor-paginate"
14
+ s.summary = "Simplified pagination for Rails API controllers"
15
+ s.description = "Wor::Paginate is a gem for Rails that simplifies pagination, particularly for controller methods, while standardizing JSON output for APIs. It's meant to work both as a standalone pagination gem and as an extra layer over Kaminari and will_paginate"
16
+ s.license = "MIT"
17
+
18
+ s.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec)/}) }
19
+ s.require_paths = ['lib']
20
+
21
+
22
+ s.add_dependency 'railties', '>= 4.1.0', '<= 5.1'
23
+ s.add_dependency 'rails', '>= 4.0'
24
+ end
metadata ADDED
@@ -0,0 +1,114 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: wor-paginate
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - hdf1986
8
+ - icoluccio
9
+ - alanhala
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2017-07-27 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: railties
17
+ requirement: !ruby/object:Gem::Requirement
18
+ requirements:
19
+ - - ">="
20
+ - !ruby/object:Gem::Version
21
+ version: 4.1.0
22
+ - - "<="
23
+ - !ruby/object:Gem::Version
24
+ version: '5.1'
25
+ type: :runtime
26
+ prerelease: false
27
+ version_requirements: !ruby/object:Gem::Requirement
28
+ requirements:
29
+ - - ">="
30
+ - !ruby/object:Gem::Version
31
+ version: 4.1.0
32
+ - - "<="
33
+ - !ruby/object:Gem::Version
34
+ version: '5.1'
35
+ - !ruby/object:Gem::Dependency
36
+ name: rails
37
+ requirement: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: '4.0'
42
+ type: :runtime
43
+ prerelease: false
44
+ version_requirements: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '4.0'
49
+ description: Wor::Paginate is a gem for Rails that simplifies pagination, particularly
50
+ for controller methods, while standardizing JSON output for APIs. It's meant to
51
+ work both as a standalone pagination gem and as an extra layer over Kaminari and
52
+ will_paginate
53
+ email:
54
+ - hugo.farji@wolox.com.ar
55
+ - ignacio.coluccio@wolox.com.ar
56
+ - alan.halatian@wolox.com.ar
57
+ executables: []
58
+ extensions: []
59
+ extra_rdoc_files: []
60
+ files:
61
+ - ".gitignore"
62
+ - ".rubocop.yml"
63
+ - ".ruby-version"
64
+ - ".travis.yml"
65
+ - CHANGELOG.md
66
+ - Gemfile
67
+ - Gemfile.lock
68
+ - LICENSE.md
69
+ - README.md
70
+ - Rakefile
71
+ - lib/generators/templates/wor_paginate.rb
72
+ - lib/generators/wor/paginate/install_generator.rb
73
+ - lib/wor/paginate.rb
74
+ - lib/wor/paginate/adapters/active_record.rb
75
+ - lib/wor/paginate/adapters/base.rb
76
+ - lib/wor/paginate/adapters/enumerable.rb
77
+ - lib/wor/paginate/adapters/kaminari.rb
78
+ - lib/wor/paginate/adapters/kaminari_already_paginated.rb
79
+ - lib/wor/paginate/adapters/will_paginate.rb
80
+ - lib/wor/paginate/adapters/will_paginate_already_paginated.rb
81
+ - lib/wor/paginate/config.rb
82
+ - lib/wor/paginate/exceptions/invalid_limit_number.rb
83
+ - lib/wor/paginate/exceptions/invalid_page_number.rb
84
+ - lib/wor/paginate/exceptions/no_pagination_adapter.rb
85
+ - lib/wor/paginate/formatter.rb
86
+ - lib/wor/paginate/paginate.rb
87
+ - lib/wor/paginate/rspec.rb
88
+ - lib/wor/paginate/version.rb
89
+ - wor-paginate.gemspec
90
+ homepage: https://github.com/Wolox/wor-paginate
91
+ licenses:
92
+ - MIT
93
+ metadata: {}
94
+ post_install_message:
95
+ rdoc_options: []
96
+ require_paths:
97
+ - lib
98
+ required_ruby_version: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ required_rubygems_version: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ requirements: []
109
+ rubyforge_project:
110
+ rubygems_version: 2.5.1
111
+ signing_key:
112
+ specification_version: 4
113
+ summary: Simplified pagination for Rails API controllers
114
+ test_files: []