diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 821318c752c..1cf3d4197d4 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -696,6 +696,7 @@ config/initializers/backtrace_silencers.rb @department-of-veterans-affairs/va-ap config/initializers/betamocks.rb @department-of-veterans-affairs/va-api-engineers @department-of-veterans-affairs/backend-review-group config/initializers/bgs.rb @department-of-veterans-affairs/Benefits-Team-1 @department-of-veterans-affairs/va-api-engineers @department-of-veterans-affairs/backend-review-group config/initializers/breakers.rb @department-of-veterans-affairs/va-api-engineers @department-of-veterans-affairs/backend-review-group +config/initializers/breakpoint.rb @department-of-veterans-affairs/va-api-engineers @department-of-veterans-affairs/backend-review-group config/initializers/clamscan.rb @department-of-veterans-affairs/va-api-engineers @department-of-veterans-affairs/backend-review-group config/initializers/config.rb @department-of-veterans-affairs/va-api-engineers @department-of-veterans-affairs/backend-review-group config/initializers/cookie_rotation.rb @department-of-veterans-affairs/va-api-engineers @department-of-veterans-affairs/backend-review-group diff --git a/.rubocop.yml b/.rubocop.yml index 4e2c5f873eb..9a66e259d65 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -342,6 +342,12 @@ RSpec/SubjectStub: Rails/FilePath: EnforcedStyle: arguments +Lint/Debugger: + DebuggerMethods: + Breakpoint: + - Breakpoint.at_receiver + - Breakpoint.at_owner + # This one doesn’t always make sense, it’s mostly the swagger, # factories and pact provider states — which need a tear_down block regardless Lint/EmptyBlock: diff --git a/config/initializers/breakpoint.rb b/config/initializers/breakpoint.rb new file mode 100644 index 00000000000..31bb8e0d167 --- /dev/null +++ b/config/initializers/breakpoint.rb @@ -0,0 +1,44 @@ +# frozen_string_literal: true + +# Only load `Breakpoint` when its only dependency, `Pry`, is loaded. If +# `Breakpoint` is ever deemed to have been loaded inappropriately, then the +# claim ought to instead be that `Pry` was loaded inappropriately. That's what +# we're expressing here. +return unless defined?(Pry) + +module Breakpoint + class << self + # Add a breakpoint at the top of an instance's method: + # `Breakpoint.at_receiver(some_instance, :some_instance_method)` + # + # Add a breakpoint at the top of a class's method: + # `Breakpoint.at_receiver(SomeClass, :some_class_method)` + def at_receiver(receiver, name) + at_owner(receiver.singleton_class, name) + end + + # Add a breakpoint at the top of a method for all of a class's instances: + # `Breakpoint.at_owner(SomeClass, :some_instance_method)` + def at_owner(owner, name) + owner.is_a?(Module) or + raise ArgumentError, 'not an owner' + + mod = + Module.new do + define_method(name) do |*args, **kwargs, &block| + # Now you have access to all the above arguments, plus whatever else + # is available in the current environment. + binding.pry # rubocop:disable Lint/Debugger + super(*args, **kwargs, &block) + end + end + + owner.prepend(mod) + end + end +end + +# Install breakpoints wherever you want if you need to investigate a particular +# instance during the execution of something, or even right here if you already +# have a handle on the thing you care about, like a class, e.g.: +# Breakpoint.at_receiver(Blueprinter::Base, :prepare_data)