wor-paginate 0.1.0

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.
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: []