From 9a28668941ba200b9679f5583a3aeb03eaa9ea71 Mon Sep 17 00:00:00 2001 From: Adam Lassek Date: Sun, 5 Nov 2023 20:34:00 -0600 Subject: [PATCH 1/2] Introduce after_register hook Allows you to take action when a new key is registered, so that you can decorate the key without knowing its name ahead of time. See also hanami/hanami#1360 --- lib/dry/system/container.rb | 9 +++++++++ spec/unit/container/hooks/after_hooks_spec.rb | 16 ++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 spec/unit/container/hooks/after_hooks_spec.rb diff --git a/lib/dry/system/container.rb b/lib/dry/system/container.rb index b324f8e48..f4bc4f878 100644 --- a/lib/dry/system/container.rb +++ b/lib/dry/system/container.rb @@ -486,6 +486,15 @@ def root config.root end + # @api public + def register(key, *) + super + + hooks[:after_register].each { |hook| instance_exec(key, &hook) } + + self + end + # @api public def resolve(key) load_component(key) unless finalized? diff --git a/spec/unit/container/hooks/after_hooks_spec.rb b/spec/unit/container/hooks/after_hooks_spec.rb new file mode 100644 index 000000000..c5e59da76 --- /dev/null +++ b/spec/unit/container/hooks/after_hooks_spec.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +RSpec.describe Dry::System::Container do + subject(:system) do + Class.new(described_class) + end + + describe "after_register hook" do + it "executes after a new key is registered" do + expect { |hook| + system.after(:register, &hook) + system.register(:foo) { "bar" } + }.to yield_with_args(:foo) + end + end +end From a54e83352b3277e05b51980ee76cadc4b186a924 Mon Sep 17 00:00:00 2001 From: Adam Lassek Date: Sun, 5 Nov 2023 20:36:52 -0600 Subject: [PATCH 2/2] Run after_finalize hooks before freeze This hook is much less useful that it might be if you could still make changes to the container when it ran. --- lib/dry/system/container.rb | 2 +- spec/unit/container/hooks/after_hooks_spec.rb | 28 +++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/lib/dry/system/container.rb b/lib/dry/system/container.rb index f4bc4f878..4f97156ef 100644 --- a/lib/dry/system/container.rb +++ b/lib/dry/system/container.rb @@ -329,8 +329,8 @@ def finalize!(freeze: true, &block) @__finalized__ = true - self.freeze if freeze hooks[:after_finalize].each { |hook| instance_eval(&hook) } + self.freeze if freeze self end diff --git a/spec/unit/container/hooks/after_hooks_spec.rb b/spec/unit/container/hooks/after_hooks_spec.rb index c5e59da76..8bae351b7 100644 --- a/spec/unit/container/hooks/after_hooks_spec.rb +++ b/spec/unit/container/hooks/after_hooks_spec.rb @@ -12,5 +12,33 @@ system.register(:foo) { "bar" } }.to yield_with_args(:foo) end + + it "provides the fully-qualified key" do + expect { |hook| + system.after(:register, &hook) + system.namespace :foo do + register(:bar) { "baz" } + end + }.to yield_with_args("foo.bar") + end + end + + describe "after_finalize hook" do + it "executes after finalization" do + expect { |hook| + system.after(:finalize, &hook) + system.finalize! + }.to yield_control + end + + it "executes before the container is frozen" do + is_frozen = nil + + system.after(:finalize) { is_frozen = frozen? } + system.finalize! + + expect(is_frozen).to eq false + expect(system).to be_frozen + end end end