From 42cb4c1ace23ecc1cce01a3671f989ad9c20e16a Mon Sep 17 00:00:00 2001 From: Dimitrij Denissenko Date: Thu, 18 Jun 2020 10:36:53 +0100 Subject: [PATCH 1/3] Preparations for v0.2.0 --- .gitignore | 1 - .rubocop.yml | 26 +++++ .travis.yml | 7 ++ Gemfile.lock | 117 ++++++++++++++++++++++ Rakefile | 9 +- grape-kaminari.gemspec | 38 +++---- lib/grape-kaminari.rb | 12 +-- lib/grape/kaminari.rb | 74 +++++++------- lib/grape/kaminari/max_value_validator.rb | 24 ++--- lib/grape/kaminari/version.rb | 2 +- spec/kaminari_spec.rb | 34 ++----- spec/paginate_helper_spec.rb | 8 +- spec/spec_helper.rb | 8 +- 13 files changed, 239 insertions(+), 121 deletions(-) create mode 100644 .rubocop.yml create mode 100644 .travis.yml create mode 100644 Gemfile.lock diff --git a/.gitignore b/.gitignore index d87d4be..8f994bd 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,6 @@ .bundle .config .yardoc -Gemfile.lock InstalledFiles _yardoc coverage diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 0000000..cdfd07c --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1,26 @@ +AllCops: + TargetRubyVersion: "2.4" + NewCops: enable + +Metrics/AbcSize: + Enabled: false +Metrics/BlockLength: + Exclude: + - spec/**/*_spec.rb +Metrics/MethodLength: + Max: 20 + +Naming/FileName: + Exclude: + - lib/grape-kaminari.rb + +Style/Documentation: + Enabled: false +Style/FrozenStringLiteralComment: + Enabled: false +Style/TrailingCommaInArguments: + EnforcedStyleForMultiline: consistent_comma +Style/TrailingCommaInArrayLiteral: + EnforcedStyleForMultiline: consistent_comma +Style/TrailingCommaInHashLiteral: + EnforcedStyleForMultiline: consistent_comma diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..dfb2aab --- /dev/null +++ b/.travis.yml @@ -0,0 +1,7 @@ +language: ruby +cache: bundler +rvm: + - 2.7 + - 2.6 + - 2.5 + - 2.4 diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 0000000..56ace3b --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,117 @@ +PATH + remote: . + specs: + grape-kaminari (0.2.0) + grape (>= 1.0) + kaminari-grape + +GEM + remote: https://rubygems.org/ + specs: + activesupport (6.0.3.2) + concurrent-ruby (~> 1.0, >= 1.0.2) + i18n (>= 0.7, < 2) + minitest (~> 5.1) + tzinfo (~> 1.1) + zeitwerk (~> 2.2, >= 2.2.2) + ast (2.4.1) + builder (3.2.4) + concurrent-ruby (1.1.6) + diff-lcs (1.3) + dry-configurable (0.11.5) + concurrent-ruby (~> 1.0) + dry-core (~> 0.4, >= 0.4.7) + dry-equalizer (~> 0.2) + dry-container (0.7.2) + concurrent-ruby (~> 1.0) + dry-configurable (~> 0.1, >= 0.1.3) + dry-core (0.4.9) + concurrent-ruby (~> 1.0) + dry-equalizer (0.3.0) + dry-inflector (0.2.0) + dry-logic (1.0.6) + concurrent-ruby (~> 1.0) + dry-core (~> 0.2) + dry-equalizer (~> 0.2) + dry-types (1.4.0) + concurrent-ruby (~> 1.0) + dry-container (~> 0.3) + dry-core (~> 0.4, >= 0.4.4) + dry-equalizer (~> 0.3) + dry-inflector (~> 0.1, >= 0.1.2) + dry-logic (~> 1.0, >= 1.0.2) + grape (1.3.3) + activesupport + builder + dry-types (>= 1.1) + mustermann-grape (~> 1.0.0) + rack (>= 1.3.0) + rack-accept + i18n (1.8.3) + concurrent-ruby (~> 1.0) + kaminari-core (1.2.1) + kaminari-grape (1.0.1) + grape + kaminari-core (~> 1.0) + minitest (5.14.1) + mustermann (1.1.1) + ruby2_keywords (~> 0.0.1) + mustermann-grape (1.0.1) + mustermann (>= 1.0.0) + parallel (1.19.2) + parser (2.7.1.3) + ast (~> 2.4.0) + rack (2.2.3) + rack-accept (0.4.5) + rack (>= 0.4) + rack-test (1.1.0) + rack (>= 1.0, < 3) + rainbow (3.0.0) + rake (13.0.1) + regexp_parser (1.7.1) + rexml (3.2.4) + rspec (3.9.0) + rspec-core (~> 3.9.0) + rspec-expectations (~> 3.9.0) + rspec-mocks (~> 3.9.0) + rspec-core (3.9.2) + rspec-support (~> 3.9.3) + rspec-expectations (3.9.2) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.9.0) + rspec-mocks (3.9.1) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.9.0) + rspec-support (3.9.3) + rubocop (0.85.1) + parallel (~> 1.10) + parser (>= 2.7.0.1) + rainbow (>= 2.2.2, < 4.0) + regexp_parser (>= 1.7) + rexml + rubocop-ast (>= 0.0.3) + ruby-progressbar (~> 1.7) + unicode-display_width (>= 1.4.0, < 2.0) + rubocop-ast (0.0.3) + parser (>= 2.7.0.1) + ruby-progressbar (1.10.1) + ruby2_keywords (0.0.2) + thread_safe (0.3.6) + tzinfo (1.2.7) + thread_safe (~> 0.1) + unicode-display_width (1.7.0) + zeitwerk (2.3.0) + +PLATFORMS + ruby + +DEPENDENCIES + bundler + grape-kaminari! + rack-test + rake + rspec + rubocop + +BUNDLED WITH + 2.1.4 diff --git a/Rakefile b/Rakefile index 32de6b4..06518ca 100644 --- a/Rakefile +++ b/Rakefile @@ -1,5 +1,8 @@ -require "bundler/gem_tasks" - -task default: :spec +require 'bundler/gem_tasks' +require 'rubocop/rake_task' require 'rspec/core/rake_task' + +RuboCop::RakeTask.new RSpec::Core::RakeTask.new + +task default: %i[rubocop spec] diff --git a/grape-kaminari.gemspec b/grape-kaminari.gemspec index 09e2199..9122dce 100644 --- a/grape-kaminari.gemspec +++ b/grape-kaminari.gemspec @@ -1,28 +1,28 @@ -# coding: utf-8 -lib = File.expand_path('../lib', __FILE__) +lib = File.expand_path('lib', __dir__) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) require 'grape/kaminari/version' Gem::Specification.new do |spec| - spec.name = "grape-kaminari" + spec.name = 'grape-kaminari' spec.version = Grape::Kaminari::VERSION - spec.authors = ["Tymon Tobolski"] - spec.email = ["tymon.tobolski@monterail.com"] - spec.description = %q{kaminari paginator integration for grape API framework} - spec.summary = %q{kaminari integration for grape} - spec.homepage = "" - spec.license = "MIT" + spec.authors = ['Tymon Tobolski', 'Black Square Media'] + spec.email = ['info@blacksquaremedia.com'] + spec.description = 'kaminari paginator integration for grape API framework' + spec.summary = 'kaminari integration for grape' + spec.homepage = '' + spec.license = 'MIT' - spec.files = `git ls-files`.split($/) - spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } - spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) - spec.require_paths = ["lib"] + spec.files = `git ls-files -z`.split("\x0").reject { |f| f.start_with?('spec/') } + spec.test_files = `git ls-files -z -- spec/*`.split("\x0") + spec.require_paths = ['lib'] + spec.required_ruby_version = '>= 2.4' + spec.add_runtime_dependency 'grape', '>= 1.0' + spec.add_runtime_dependency 'kaminari-grape' - spec.add_runtime_dependency "grape" - spec.add_runtime_dependency "kaminari" - - spec.add_development_dependency "bundler", "~> 1.3" - spec.add_development_dependency "rake" - spec.add_development_dependency 'rspec', '~> 2.9' + spec.add_development_dependency 'bundler' + spec.add_development_dependency 'rack-test' + spec.add_development_dependency 'rake' + spec.add_development_dependency 'rspec' + spec.add_development_dependency 'rubocop' end diff --git a/lib/grape-kaminari.rb b/lib/grape-kaminari.rb index 52fea6a..31cd9fa 100644 --- a/lib/grape-kaminari.rb +++ b/lib/grape-kaminari.rb @@ -1,11 +1 @@ -module Grape - module Kaminari - class << self - def post_0_9_0_grape? - Gem::Version.new(Grape::VERSION) > Gem::Version.new('0.9.0') - end - end - end -end - -require "grape/kaminari" +require 'grape/kaminari' diff --git a/lib/grape/kaminari.rb b/lib/grape/kaminari.rb index d7d1fa7..7eb3728 100644 --- a/lib/grape/kaminari.rb +++ b/lib/grape/kaminari.rb @@ -1,45 +1,51 @@ -require "grape" -require "grape/kaminari/version" -require "grape/kaminari/max_value_validator" -require "kaminari/grape" +require 'grape' +require 'grape/kaminari/version' +require 'grape/kaminari/max_value_validator' +require 'kaminari/grape' module Grape module Kaminari - def self.included(base) - base.class_eval do - helpers do - def paginate(collection) - collection.page(params[:page].to_i).per(params[:per_page].to_i).padding(params[:offset].to_i).tap do |data| - header "X-Total", data.total_count.to_s - header "X-Total-Pages", data.total_pages.to_s - header "X-Per-Page", data.limit_value.to_s - header "X-Page", data.current_page.to_s - header "X-Next-Page", data.next_page.to_s - header "X-Prev-Page", data.prev_page.to_s - header "X-Offset", params[:offset].to_s - end - end + module HelperMethods # :nodoc: + def paginate(collection) + collection.page(params[:page].to_i) + .per(params[:per_page].to_i) + .padding(params[:offset].to_i) + .tap do |data| + header 'X-Total', data.total_count.to_s + header 'X-Total-Pages', data.total_pages.to_s + header 'X-Per-Page', data.limit_value.to_s + header 'X-Page', data.current_page.to_s + header 'X-Next-Page', data.next_page.to_s + header 'X-Prev-Page', data.prev_page.to_s + header 'X-Offset', params[:offset].to_s end + end + end - def self.paginate(options = {}) - options.reverse_merge!( - per_page: ::Kaminari.config.default_per_page || 10, - max_per_page: ::Kaminari.config.max_per_page, - offset: 0 - ) - params do - optional :page, type: Integer, default: 1, - desc: 'Page offset to fetch.' - optional :per_page, type: Integer, default: options[:per_page], - desc: 'Number of results to return per page.', - max_value: options[:max_per_page] - if options[:offset].is_a? Numeric - optional :offset, type: Integer, default: options[:offset], - desc: 'Pad a number of results.' - end + module ClassMethods # :nodoc: + def paginate(**options) + options.reverse_merge!( + per_page: ::Kaminari.config.default_per_page || 10, + max_per_page: ::Kaminari.config.max_per_page, + offset: 0, + ) + params do + optional :page, type: Integer, default: 1, + desc: 'Page offset to fetch.' + optional :per_page, type: Integer, default: options[:per_page], + desc: 'Number of results to return per page.', + max_value: options[:max_per_page] + if options[:offset].is_a? Numeric + optional :offset, type: Integer, default: options[:offset], + desc: 'Pad a number of results.' end end end end + + def self.included(base) + base.helpers HelperMethods + base.extend ClassMethods + end end end diff --git a/lib/grape/kaminari/max_value_validator.rb b/lib/grape/kaminari/max_value_validator.rb index d300595..61c1281 100644 --- a/lib/grape/kaminari/max_value_validator.rb +++ b/lib/grape/kaminari/max_value_validator.rb @@ -1,24 +1,14 @@ module Grape module Kaminari - base = if post_0_9_0_grape? - Grape::Validations::Base - else - Grape::Validations::SingleOptionValidator - end - - class MaxValueValidator < base + class MaxValueValidator < Grape::Validations::Base def validate_param!(attr_name, params) - return unless params[attr_name] - attr = params[attr_name] - if attr && @option && attr > @option - message = "must be less than or equal #{@option}" - if Gem::Version.new(Grape::VERSION) >= Gem::Version.new('0.9.0') - raise Grape::Exceptions::Validation, params: [@scope.full_name(attr_name)], message: message - else - raise Grape::Exceptions::Validation, param: @scope.full_name(attr_name), message: message - end - end + return unless attr && @option && attr > @option + + raise Grape::Exceptions::Validation.new( + params: [@scope.full_name(attr_name)], + message: "must be less than or equal #{@option}", + ) end end end diff --git a/lib/grape/kaminari/version.rb b/lib/grape/kaminari/version.rb index 2fca9f0..89f22e5 100644 --- a/lib/grape/kaminari/version.rb +++ b/lib/grape/kaminari/version.rb @@ -1,5 +1,5 @@ module Grape module Kaminari - VERSION = "0.1.9" + VERSION = '0.2.0'.freeze end end diff --git a/spec/kaminari_spec.rb b/spec/kaminari_spec.rb index 6a80df1..1ad0dca 100644 --- a/spec/kaminari_spec.rb +++ b/spec/kaminari_spec.rb @@ -9,7 +9,6 @@ class PaginatedAPI < Grape::API end describe Grape::Kaminari do - describe 'unpaginated api' do subject { Class.new(UnPaginatedAPI) } @@ -23,19 +22,16 @@ class PaginatedAPI < Grape::API it 'adds to declared parameters' do subject.paginate - if Grape::Kaminari.post_0_9_0_grape? - expect(subject.inheritable_setting.route[:declared_params]).to eq([:page, :per_page, :offset]) - else - expect(subject.settings[:declared_params]).to eq([:page, :per_page, :offset]) - end + expect(subject.inheritable_setting.route[:declared_params]).to eq(%i[page per_page offset]) end describe 'descriptions, validation, and defaults' do + let(:params) { subject.routes.first.params } + before do subject.paginate - subject.get '/' do; end + subject.get('/') {} end - let(:params) {subject.routes.first.route_params} it 'does not require :page' do expect(params['page'][:required]).to eq(false) @@ -84,21 +80,18 @@ class PaginatedAPI < Grape::API it 'defaults :offset to 0' do expect(params['offset'][:default]).to eq(0) end - - end - end describe 'custom paginated api' do subject { Class.new(PaginatedAPI) } - def app; subject; end + let(:app) { subject } + let(:params) { subject.routes.first.params } before do - subject.paginate per_page:99, max_per_page: 999, offset: 9 - subject.get '/' do; end + subject.paginate per_page: 99, max_per_page: 999, offset: 9 + subject.get('/') {} end - let(:params) {subject.routes.first.route_params} it 'defaults :per_page to customized value' do expect(params['per_page'][:default]).to eq(99) @@ -112,13 +105,12 @@ def app; subject; end it 'ensures :per_page is within :max_value' do get('/', page: 1, per_page: 1_000) expect(last_response.status).to eq 400 - expect(last_response.body).to match /per_page must be less than or equal 999/ + expect(last_response.body).to match(/per_page must be less than or equal 999/) end it 'defaults :offset to customized value' do expect(params['offset'][:default]).to eq(9) end - end describe 'paginated api without :offset' do @@ -126,13 +118,7 @@ def app; subject; end it 'excludes :offset from declared params' do subject.paginate offset: false - if Grape::Kaminari.post_0_9_0_grape? - expect(subject.inheritable_setting.route[:declared_params]).not_to include(:offset) - else - expect(subject.settings[:declared_params]).not_to include(:offset) - end + expect(subject.inheritable_setting.route[:declared_params]).not_to include(:offset) end - end - end diff --git a/spec/paginate_helper_spec.rb b/spec/paginate_helper_spec.rb index 0f0575a..ba349e0 100644 --- a/spec/paginate_helper_spec.rb +++ b/spec/paginate_helper_spec.rb @@ -17,12 +17,13 @@ class PaginatedAPI < Grape::API describe Grape::Kaminari do subject { PaginatedAPI.new } - def app; subject; end + def app + subject + end let(:json) { JSON.parse(last_response.body) } let(:header) { last_response.header } describe 'paginated helper' do - it 'returns the first page' do get '/', page: 1, per_page: 3 expect(json).to eq [1, 2, 3] @@ -50,8 +51,5 @@ def app; subject; end expect(header['X-Prev-Page']).to eq '2' expect(header['X-Offset']).to eq '1' end - end - - end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 6c8b3e6..fe6c58c 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,19 +1,15 @@ -$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib')) -$LOAD_PATH.unshift(File.dirname(__FILE__)) require 'rspec' -require 'kaminari' -require 'grape' require 'grape-kaminari' require 'rack/test' # Requires supporting files with custom matchers and macros, etc, # in ./support/ and its subdirectories. -Dir['#{File.dirname(__FILE__)}/support/**/*.rb'].each {|f| require f} +Dir[File.expand_path('./support/**/*.rb', __dir__)].sort.each { |f| require f } I18n.enforce_available_locales = false RSpec.configure do |config| config.include Rack::Test::Methods - config.treat_symbols_as_metadata_keys_with_true_values = true + config.raise_errors_for_deprecations! config.order = 'random' end From ef9fc75b7467c5a940c370baed864c815e8c5491 Mon Sep 17 00:00:00 2001 From: Dimitrij Denissenko Date: Thu, 18 Jun 2020 10:46:22 +0100 Subject: [PATCH 2/3] Update README --- LICENSE.txt | 1 + README.md | 9 ++++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/LICENSE.txt b/LICENSE.txt index f7da62a..f72b8ad 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,6 +1,7 @@ The MIT License (MIT) Copyright (c) 2013-2014 Monterail.com LLC +Copyright (c) 2020 Black Square Media Ltd Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in diff --git a/README.md b/README.md index f0a5957..b8d9124 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,9 @@ -# Grape::Kaminari [![Gem Version](https://badge.fury.io/rb/grape-kaminari.png)](http://badge.fury.io/rb/grape-kaminari) [![Circle CI](https://circleci.com/gh/monterail/grape-kaminari.png?style=shield)](https://circleci.com/gh/monterail/grape-kaminari) +# Grape::Kaminari -[kaminari](https://github.com/amatsuda/kaminari) paginator integration for [grape](https://github.com/intridea/grape) API framework. +[![Build Status](https://travis-ci.org/bsm/grape-kaminari.png?branch=master)](https://travis-ci.org/bsm/grape-kaminari) +[![License](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT) + +[kaminari](https://github.com/kaminari/kaminari) paginator integration for [grape](https://github.com/intridea/grape) API framework. ## Installation @@ -87,4 +90,4 @@ X-Offset: 10 ## Contributing -Bug reports and pull requests are welcome on GitHub at https://github.com/teamon/tesla. +Bug reports and pull requests are welcome on GitHub at https://github.com/bsm/grape-kaminari. From d0338bb91173dac36f5f7ffa5d6e2b8a04082d01 Mon Sep 17 00:00:00 2001 From: Dimitrij Denissenko Date: Thu, 18 Jun 2020 10:47:22 +0100 Subject: [PATCH 3/3] At least Ruby 2.5 --- .rubocop.yml | 2 +- .travis.yml | 1 - grape-kaminari.gemspec | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index cdfd07c..0d3dc41 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,5 +1,5 @@ AllCops: - TargetRubyVersion: "2.4" + TargetRubyVersion: "2.5" NewCops: enable Metrics/AbcSize: diff --git a/.travis.yml b/.travis.yml index dfb2aab..b2552e0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,4 +4,3 @@ rvm: - 2.7 - 2.6 - 2.5 - - 2.4 diff --git a/grape-kaminari.gemspec b/grape-kaminari.gemspec index 9122dce..c9aad7d 100644 --- a/grape-kaminari.gemspec +++ b/grape-kaminari.gemspec @@ -15,7 +15,7 @@ Gem::Specification.new do |spec| spec.files = `git ls-files -z`.split("\x0").reject { |f| f.start_with?('spec/') } spec.test_files = `git ls-files -z -- spec/*`.split("\x0") spec.require_paths = ['lib'] - spec.required_ruby_version = '>= 2.4' + spec.required_ruby_version = '>= 2.5' spec.add_runtime_dependency 'grape', '>= 1.0' spec.add_runtime_dependency 'kaminari-grape'