diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d79b49f95a..40bd96b671 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -24,7 +24,7 @@ jobs: fail-fast: false matrix: ruby: ['2.7', '3.0', '3.1', '3.2'] - gemfile: [rack_2_0, rack_3_0, rails_6_0, rails_6_1, rails_7_0] + gemfile: [rack_2_0, rack_3_0, rails_6_0, rails_6_1, rails_7_0, rails_7_1] include: - ruby: '2.6' gemfile: rails_5_2 @@ -78,4 +78,4 @@ jobs: uses: coverallsapp/github-action@master with: github-token: ${{ secrets.github_token }} - parallel-finished: true \ No newline at end of file + parallel-finished: true diff --git a/CHANGELOG.md b/CHANGELOG.md index 8d550bc29e..f8dc826bc6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ #### Features +* [#2353](https://github.com/ruby-grape/grape/pull/2353): Added Rails 7.1 support - [@ericproulx](https://github.com/ericproulx). * Your contribution here. #### Fixes diff --git a/README.md b/README.md index b37f12b9f1..b0fe3375f5 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ - [Grape for Enterprise](#grape-for-enterprise) - [Installation](#installation) - [Basic Usage](#basic-usage) +- [Rails 7.1](#rails-71) - [Mounting](#mounting) - [All](#all) - [Rack](#rack) @@ -179,7 +180,7 @@ The maintainers of Grape are working with Tidelift to deliver commercial support ## Installation -Ruby 2.4 or newer is required. +Ruby 2.6 or newer is required. Grape is available as a gem, to install it run: @@ -268,6 +269,10 @@ module Twitter end ``` +## Rails 7.1 + +Grape's [deprecator](https://api.rubyonrails.org/v7.1.0/classes/ActiveSupport/Deprecation.html) will be added to your application's deprecators [automatically](lib/grape/railtie.rb) as `:grape`, so that your application's configuration can be applied to it. + ## Mounting ### All diff --git a/gemfiles/rails_7_1.gemfile b/gemfiles/rails_7_1.gemfile new file mode 100644 index 0000000000..01fbd7900d --- /dev/null +++ b/gemfiles/rails_7_1.gemfile @@ -0,0 +1,45 @@ +# frozen_string_literal: true + +# This file was generated by Appraisal + +source 'https://rubygems.org' + +gem 'rails', '~> 7.1.0' +gem 'tzinfo-data', require: false + +group :development, :test do + gem 'bundler' + gem 'hashie' + gem 'rake' + gem 'rubocop', '1.50.2', require: false + gem 'rubocop-performance', '1.17.1', require: false + gem 'rubocop-rspec', '2.20.0', require: false +end + +group :development do + gem 'appraisal' + gem 'benchmark-ips' + gem 'benchmark-memory' + gem 'guard' + gem 'guard-rspec' + gem 'guard-rubocop' +end + +group :test do + gem 'cookiejar' + gem 'grape-entity', '~> 0.6' + gem 'mime-types' + gem 'rack-jsonp', require: 'rack/jsonp' + gem 'rack-test', '< 2.1' + gem 'rspec', '< 4' + gem 'ruby-grape-danger', '~> 0.2.0', require: false + gem 'simplecov', '~> 0.21.2' + gem 'simplecov-lcov', '~> 0.8.0' + gem 'test-prof', require: false +end + +platforms :jruby do + gem 'racc' +end + +gemspec path: '../' diff --git a/lib/grape.rb b/lib/grape.rb index 39f3905c07..680bea819f 100644 --- a/lib/grape.rb +++ b/lib/grape.rb @@ -38,6 +38,10 @@ module Grape include ActiveSupport::Configurable extend ::ActiveSupport::Autoload + def self.deprecator + @deprecator ||= ActiveSupport::Deprecation.new('2.0', 'Grape') + end + eager_autoload do autoload :API autoload :Endpoint @@ -301,5 +305,8 @@ module Types require 'grape/util/lazy_value' require 'grape/util/lazy_block' require 'grape/util/endpoint_configuration' - require 'grape/version' + +# https://api.rubyonrails.org/classes/ActiveSupport/Deprecation.html +# adding Grape.deprecator to Rails App if any +require 'grape/railtie' if defined?(Rails::Railtie) && ActiveSupport.gem_version >= Gem::Version.new('7.1') diff --git a/lib/grape/dsl/desc.rb b/lib/grape/dsl/desc.rb index 64d5eed910..e1611bf7f2 100644 --- a/lib/grape/dsl/desc.rb +++ b/lib/grape/dsl/desc.rb @@ -68,7 +68,7 @@ def desc(description, options = {}, &config_block) end config_class.configure(&config_block) - ActiveSupport::Deprecation.warn('Passing a options hash and a block to `desc` is deprecated. Move all hash options to block.') if options.any? + Grape.deprecator.warn('Passing a options hash and a block to `desc` is deprecated. Move all hash options to block.') if options.any? options = config_class.settings else options = options.merge(description: description) diff --git a/lib/grape/dsl/inside_route.rb b/lib/grape/dsl/inside_route.rb index 4299888722..7023d69dd9 100644 --- a/lib/grape/dsl/inside_route.rb +++ b/lib/grape/dsl/inside_route.rb @@ -280,13 +280,13 @@ def return_no_content # Deprecated method to send files to the client. Use `sendfile` or `stream` def file(value = nil) if value.is_a?(String) - ActiveSupport::Deprecation.warn('Use sendfile or stream to send files.') + Grape.deprecator.warn('Use sendfile or stream to send files.') sendfile(value) elsif !value.is_a?(NilClass) - ActiveSupport::Deprecation.warn('Use stream to use a Stream object.') + Grape.deprecator.warn('Use stream to use a Stream object.') stream(value) else - ActiveSupport::Deprecation.warn('Use sendfile or stream to send files.') + Grape.deprecator.warn('Use sendfile or stream to send files.') sendfile end end diff --git a/lib/grape/exceptions/missing_group_type.rb b/lib/grape/exceptions/missing_group_type.rb index 1f104321f5..9a7d3180a0 100644 --- a/lib/grape/exceptions/missing_group_type.rb +++ b/lib/grape/exceptions/missing_group_type.rb @@ -10,4 +10,4 @@ def initialize end end -Grape::Exceptions::MissingGroupTypeError = ActiveSupport::Deprecation::DeprecatedConstantProxy.new('Grape::Exceptions::MissingGroupTypeError', 'Grape::Exceptions::MissingGroupType') +Grape::Exceptions::MissingGroupTypeError = ActiveSupport::Deprecation::DeprecatedConstantProxy.new('Grape::Exceptions::MissingGroupTypeError', 'Grape::Exceptions::MissingGroupType', Grape.deprecator) diff --git a/lib/grape/exceptions/unsupported_group_type.rb b/lib/grape/exceptions/unsupported_group_type.rb index da45abafdd..4c5e6396a3 100644 --- a/lib/grape/exceptions/unsupported_group_type.rb +++ b/lib/grape/exceptions/unsupported_group_type.rb @@ -10,4 +10,4 @@ def initialize end end -Grape::Exceptions::UnsupportedGroupTypeError = ActiveSupport::Deprecation::DeprecatedConstantProxy.new('Grape::Exceptions::UnsupportedGroupTypeError', 'Grape::Exceptions::UnsupportedGroupType') +Grape::Exceptions::UnsupportedGroupTypeError = ActiveSupport::Deprecation::DeprecatedConstantProxy.new('Grape::Exceptions::UnsupportedGroupTypeError', 'Grape::Exceptions::UnsupportedGroupType', Grape.deprecator) diff --git a/lib/grape/railtie.rb b/lib/grape/railtie.rb new file mode 100644 index 0000000000..42eb3442cb --- /dev/null +++ b/lib/grape/railtie.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +module Grape + class Railtie < ::Rails::Railtie + initializer 'grape.deprecator' do |app| + app.deprecators[:grape] = Grape.deprecator + end + end +end diff --git a/lib/grape/router/route.rb b/lib/grape/router/route.rb index 7bbfe6a0c5..d5600df1c9 100644 --- a/lib/grape/router/route.rb +++ b/lib/grape/router/route.rb @@ -84,7 +84,7 @@ def warn_route_methods(name, location, expected = nil) path, line = *location.scan(SOURCE_LOCATION_REGEXP).first path = File.realpath(path) if Pathname.new(path).relative? expected ||= name - ActiveSupport::Deprecation.warn("#{path}:#{line}: The route_xxx methods such as route_#{name} have been deprecated, please use #{expected}.") + Grape.deprecator.warn("#{path}:#{line}: The route_xxx methods such as route_#{name} have been deprecated, please use #{expected}.") end end end diff --git a/lib/grape/validations/validators/base.rb b/lib/grape/validations/validators/base.rb index ae0f0f48e5..c76eb4b394 100644 --- a/lib/grape/validations/validators/base.rb +++ b/lib/grape/validations/validators/base.rb @@ -85,7 +85,7 @@ def fail_fast? Grape::Validations::Base = Class.new(Grape::Validations::Validators::Base) do def self.inherited(*) - ActiveSupport::Deprecation.warn 'Grape::Validations::Base is deprecated! Use Grape::Validations::Validators::Base instead.' + Grape.deprecator.warn 'Grape::Validations::Base is deprecated! Use Grape::Validations::Validators::Base instead.' super end end diff --git a/lib/grape/validations/validators/values_validator.rb b/lib/grape/validations/validators/values_validator.rb index 2b7aca76ed..3be7d609b6 100644 --- a/lib/grape/validations/validators/values_validator.rb +++ b/lib/grape/validations/validators/values_validator.rb @@ -10,11 +10,11 @@ def initialize(attrs, options, required, scope, **opts) @values = options[:value] @proc = options[:proc] - ActiveSupport::Deprecation.warn('The values validator except option is deprecated. Use the except validator instead.') if @excepts + Grape.deprecator.warn('The values validator except option is deprecated. Use the except validator instead.') if @excepts raise ArgumentError, 'proc must be a Proc' if @proc && !@proc.is_a?(Proc) - ActiveSupport::Deprecation.warn('The values validator proc option is deprecated. The lambda expression can now be assigned directly to values.') if @proc + Grape.deprecator.warn('The values validator proc option is deprecated. The lambda expression can now be assigned directly to values.') if @proc else @excepts = nil @values = nil diff --git a/spec/config/spec_test_prof.rb b/spec/config/spec_test_prof.rb new file mode 100644 index 0000000000..e5259e110b --- /dev/null +++ b/spec/config/spec_test_prof.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +require 'test_prof/recipes/rspec/let_it_be' + +TestProf::BeforeAll.adapter = Class.new do + def begin_transaction; end + + def rollback_transaction; end +end.new diff --git a/spec/grape/dsl/desc_spec.rb b/spec/grape/dsl/desc_spec.rb index c2acde9105..fa3ae7f9ea 100644 --- a/spec/grape/dsl/desc_spec.rb +++ b/spec/grape/dsl/desc_spec.rb @@ -83,7 +83,7 @@ end it 'can be set with options and a block' do - expect(ActiveSupport::Deprecation).to receive(:warn).with('Passing a options hash and a block to `desc` is deprecated. Move all hash options to block.') + expect(Grape.deprecator).to receive(:warn).with('Passing a options hash and a block to `desc` is deprecated. Move all hash options to block.') desc_text = 'The description' detail_text = 'more details' diff --git a/spec/grape/dsl/inside_route_spec.rb b/spec/grape/dsl/inside_route_spec.rb index e9a529b513..9547af46b2 100644 --- a/spec/grape/dsl/inside_route_spec.rb +++ b/spec/grape/dsl/inside_route_spec.rb @@ -208,7 +208,7 @@ def initialize let(:file_path) { '/some/file/path' } it 'emits a warning that this method is deprecated' do - expect(ActiveSupport::Deprecation).to receive(:warn).with(/Use sendfile or stream/) + expect(Grape.deprecator).to receive(:warn).with(/Use sendfile or stream/) subject.file file_path end @@ -224,7 +224,7 @@ def initialize let(:file_object) { double('StreamerObject', each: nil) } it 'emits a warning that this method is deprecated' do - expect(ActiveSupport::Deprecation).to receive(:warn).with(/Use stream to use a Stream object/) + expect(Grape.deprecator).to receive(:warn).with(/Use stream to use a Stream object/) subject.file file_object end @@ -239,7 +239,7 @@ def initialize describe 'get' do it 'emits a warning that this method is deprecated' do - expect(ActiveSupport::Deprecation).to receive(:warn).with(/Use sendfile or stream/) + expect(Grape.deprecator).to receive(:warn).with(/Use sendfile or stream/) subject.file end @@ -269,7 +269,7 @@ def initialize end it 'sends no deprecation warnings' do - expect(ActiveSupport::Deprecation).not_to receive(:warn) + expect(Grape.deprecator).not_to receive(:warn) subject.sendfile file_path end @@ -330,7 +330,7 @@ def initialize end it 'emits no deprecation warnings' do - expect(ActiveSupport::Deprecation).not_to receive(:warn) + expect(Grape.deprecator).not_to receive(:warn) subject.stream file_path end @@ -380,7 +380,7 @@ def initialize end it 'emits no deprecation warnings' do - expect(ActiveSupport::Deprecation).not_to receive(:warn) + expect(Grape.deprecator).not_to receive(:warn) subject.stream stream_object end diff --git a/spec/grape/railtie_spec.rb b/spec/grape/railtie_spec.rb new file mode 100644 index 0000000000..4a95551087 --- /dev/null +++ b/spec/grape/railtie_spec.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +if defined?(Rails::Railtie) && ActiveSupport.gem_version >= Gem::Version.new('7.1') + describe Grape::Railtie do + describe '.railtie' do + subject { test_app.deprecators[:grape] } + + let(:test_app) do + Class.new(Rails::Application) do + config.eager_load = false + config.load_defaults 7.1 + end + end + + before { test_app.initialize! } + + it { is_expected.to be(Grape.deprecator) } + end + end +end diff --git a/spec/shared/deprecated_class_examples.rb b/spec/shared/deprecated_class_examples.rb index 93a4f120cf..7909798ea8 100644 --- a/spec/shared/deprecated_class_examples.rb +++ b/spec/shared/deprecated_class_examples.rb @@ -4,10 +4,10 @@ subject { deprecated_class.new } around do |example| - old_deprec_behavior = ActiveSupport::Deprecation.behavior - ActiveSupport::Deprecation.behavior = :raise + old_deprec_behavior = Grape.deprecator.behavior + Grape.deprecator.behavior = :raise example.run - ActiveSupport::Deprecation.behavior = old_deprec_behavior + Grape.deprecator.behavior = old_deprec_behavior end it 'raises an ActiveSupport::DeprecationException' do diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index f09fdd3567..1a2581ae75 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -4,23 +4,16 @@ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib')) $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), 'support')) -require 'grape' -require 'test_prof/recipes/rspec/let_it_be' - -class NullAdapter - def begin_transaction; end - - def rollback_transaction; end -end - -TestProf::BeforeAll.adapter = NullAdapter.new - require 'rubygems' require 'bundler' Bundler.require :default, :test -Dir["#{File.dirname(__FILE__)}/support/*.rb"].sort.each do |file| - require file +require 'grape' + +%w[config support].each do |dir| + Dir["#{File.dirname(__FILE__)}/#{dir}/**/*.rb"].sort.each do |file| + require file + end end # The default value for this setting is true in a standard Rails app,