From efd87b07411612ba024ac36134b27ee549f03215 Mon Sep 17 00:00:00 2001 From: Yutaka Kamei Date: Tue, 5 Apr 2022 08:45:30 +0900 Subject: [PATCH] Support deprecation.rails (#89) --- README.md | 2 +- lib/rails_band.rb | 1 + lib/rails_band/deprecation_subscriber.rb | 40 +++++++++++++ lib/rails_band/railtie.rb | 3 + .../dummy/app/controllers/users_controller.rb | 6 ++ test/dummy/config/routes.rb | 1 + .../rails_band/deprecation_subscriber_test.rb | 56 +++++++++++++++++++ 7 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 lib/rails_band/deprecation_subscriber.rb create mode 100644 test/rails_band/deprecation_subscriber_test.rb diff --git a/README.md b/README.md index c9f8833f..924ad106 100644 --- a/README.md +++ b/README.md @@ -162,7 +162,7 @@ These are Rails Instrumentation API hooks supported by this gem so far. | Event name | Supported | | ----------------------------------------------------------------------------------------------------------- | --------- | -| [`deprecation.rails`](https://guides.rubyonrails.org/active_support_instrumentation.html#deprecation-rails) | | +| [`deprecation.rails`](https://guides.rubyonrails.org/active_support_instrumentation.html#deprecation-rails) | ✅ | ## Contributing diff --git a/lib/rails_band.rb b/lib/rails_band.rb index 1efb0701..122cde00 100644 --- a/lib/rails_band.rb +++ b/lib/rails_band.rb @@ -3,6 +3,7 @@ require 'rails_band/version' require 'rails_band/configuration' require 'rails_band/base_event' +require 'rails_band/deprecation_subscriber' require 'rails_band/railtie' # Rails::Band unsubscribes all default LogSubscribers from Rails Instrumentation API, diff --git a/lib/rails_band/deprecation_subscriber.rb b/lib/rails_band/deprecation_subscriber.rb new file mode 100644 index 00000000..2ca9db6f --- /dev/null +++ b/lib/rails_band/deprecation_subscriber.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true + +module RailsBand + # DeprecationSubscriber is responsible for logging deprecation warnings. + class DeprecationSubscriber < ::ActiveSupport::LogSubscriber + # DeprecationEvent is a wrapper around a deprecation notification event. + class DeprecationEvent < BaseEvent + def message + @message ||= @event.payload.fetch(:message) + end + + def callstack + @callstack ||= @event.payload.fetch(:callstack) + end + + def gem_name + @gem_name ||= @event.payload.fetch(:gem_name) + end + + def deprecation_horizon + @deprecation_horizon ||= @event.payload.fetch(:deprecation_horizon) + end + end + + mattr_accessor :consumers + + def deprecation(event) + consumer&.call(DeprecationEvent.new(event)) + end + + private + + def consumer + # HACK: ActiveSupport::Subscriber has the instance variable @namespace, but it's not documented. + # This hack might possibly break in the future. + namespace = self.class.instance_variable_get(:@namespace) + consumers[:"deprecation.#{namespace}"] || consumers[:deprecation] || consumers[:default] + end + end +end diff --git a/lib/rails_band/railtie.rb b/lib/rails_band/railtie.rb index c8991522..e960af38 100644 --- a/lib/rails_band/railtie.rb +++ b/lib/rails_band/railtie.rb @@ -43,6 +43,9 @@ class Railtie < ::Rails::Railtie RailsBand::ActiveSupport::LogSubscriber.consumers = consumers RailsBand::ActiveSupport::LogSubscriber.attach_to :active_support + RailsBand::DeprecationSubscriber.consumers = consumers + RailsBand::DeprecationSubscriber.attach_to :rails + if defined?(::ActiveJob) require 'active_job/logging' diff --git a/test/dummy/app/controllers/users_controller.rb b/test/dummy/app/controllers/users_controller.rb index 0437126c..23951135 100644 --- a/test/dummy/app/controllers/users_controller.rb +++ b/test/dummy/app/controllers/users_controller.rb @@ -93,6 +93,12 @@ def cache3 redirect_to users_path end + def deprecation + ActiveSupport::Deprecation.behavior = :notify + ActiveSupport::Deprecation.warn('deprecated!!!') + redirect_to users_path + end + private def halt! diff --git a/test/dummy/config/routes.rb b/test/dummy/config/routes.rb index d7215741..e35117e1 100644 --- a/test/dummy/config/routes.rb +++ b/test/dummy/config/routes.rb @@ -12,6 +12,7 @@ get :cache get :cache2 get :cache3 + get :deprecation end resources :yay, only: %i[index show] diff --git a/test/rails_band/deprecation_subscriber_test.rb b/test/rails_band/deprecation_subscriber_test.rb new file mode 100644 index 00000000..56c6dbc6 --- /dev/null +++ b/test/rails_band/deprecation_subscriber_test.rb @@ -0,0 +1,56 @@ +# frozen_string_literal: true + +require 'test_helper' + +class DeprecationSubscriberTest < ActionDispatch::IntegrationTest + setup do + @event = nil + end + + test 'use the consumer with the exact event name' do # rubocop:disable Minitest/MultipleAssertions + RailsBand::DeprecationSubscriber.consumers = { + 'deprecation.rails': ->(event) { @event = event } + } + get '/users/1/deprecation' + assert_match(/DEPRECATION WARNING: deprecated!!!/, @event.message) + assert_equal 'Rails', @event.gem_name + assert_instance_of String, @event.deprecation_horizon + @event.callstack.each do |location| + assert_instance_of Thread::Backtrace::Location, location + end + end + + test 'use the consumer with namespace' do # rubocop:disable Minitest/MultipleAssertions + RailsBand::DeprecationSubscriber.consumers = { + deprecation: ->(event) { @event = event } + } + get '/users/1/deprecation' + assert_match(/DEPRECATION WARNING: deprecated!!!/, @event.message) + assert_equal 'Rails', @event.gem_name + assert_instance_of String, @event.deprecation_horizon + @event.callstack.each do |location| + assert_instance_of Thread::Backtrace::Location, location + end + end + + test 'use the consumer with default' do # rubocop:disable Minitest/MultipleAssertions + RailsBand::DeprecationSubscriber.consumers = { + default: ->(event) { @event = event } + } + get '/users/1/deprecation' + assert_match(/DEPRECATION WARNING: deprecated!!!/, @event.message) + assert_equal 'Rails', @event.gem_name + assert_instance_of String, @event.deprecation_horizon + @event.callstack.each do |location| + assert_instance_of Thread::Backtrace::Location, location + end + end + + test 'do not use the consumer because the event is not for the target' do + RailsBand::DeprecationSubscriber.consumers = { + 'unknown.rails': ->(event) { @event = event } + } + get '/users/1/deprecation' + assert_nil @event + end +end