From aff8705cf6baf3ab55ec8d25d6c19b9c436ac7a0 Mon Sep 17 00:00:00 2001 From: Sean Gregory Date: Sun, 4 Jul 2021 09:09:16 -0400 Subject: [PATCH 01/15] replace settings --- lib/dry/configurable/settings.rb | 7 ++++ .../dry/configurable/setting_spec.rb | 38 +++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/lib/dry/configurable/settings.rb b/lib/dry/configurable/settings.rb index 3784e17d..a92f799b 100644 --- a/lib/dry/configurable/settings.rb +++ b/lib/dry/configurable/settings.rb @@ -23,6 +23,13 @@ def initialize(elements = EMPTY_ARRAY) initialize_elements(elements) end + def replace(settings) + raise ArgumentError, "settings must be a Dry::Configurable::Settings" unless settings.is_a? Dry::Configurable::Settings + settings.each do |setting| + self << setting + end + end + # @api private def <<(setting) elements[setting.name] = setting diff --git a/spec/integration/dry/configurable/setting_spec.rb b/spec/integration/dry/configurable/setting_spec.rb index cb981120..5d7a3ebc 100644 --- a/spec/integration/dry/configurable/setting_spec.rb +++ b/spec/integration/dry/configurable/setting_spec.rb @@ -185,6 +185,44 @@ include_context "configurable behavior" + context "can be configured with another class's settings" do + let(:other_klass) do + Class.new do + extend Dry::Configurable + end + end + + it "replaces with each" do + klass.setting :hello, "world" + klass._settings.each do |setting| + other_klass._settings << setting.dup + end + expect(other_klass.config.hello).to eql("world") + end + + it "replaces with replace" do + klass.setting :hello, "world" + other_klass._settings.replace(klass._settings.dup) + expect(other_klass.config.hello).to eql("world") + end + + it "deep replace" do + klass.setting :database do + setting :dsn, "localhost" + end + + other_klass._settings.replace(klass._settings.dup) + expect(other_klass.config.database.dsn).to eql('localhost') + end + + it "throws an error if the settings aren't Dry::Configurable::Settings" do + klass.setting :hello, "world" + expect{ other_klass._settings.replace(klass) }.to raise_error do |error| + expect(error.class).to be(ArgumentError) + end + end + end + context "with a subclass" do let(:subclass) do Class.new(klass) From 5352a895e6f35a7da677fed79aa0c97f6fb37a76 Mon Sep 17 00:00:00 2001 From: Sean Gregory Date: Sun, 4 Jul 2021 09:52:41 -0400 Subject: [PATCH 02/15] fix formatting --- lib/dry/configurable/settings.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/dry/configurable/settings.rb b/lib/dry/configurable/settings.rb index a92f799b..c4910ffe 100644 --- a/lib/dry/configurable/settings.rb +++ b/lib/dry/configurable/settings.rb @@ -24,7 +24,10 @@ def initialize(elements = EMPTY_ARRAY) end def replace(settings) - raise ArgumentError, "settings must be a Dry::Configurable::Settings" unless settings.is_a? Dry::Configurable::Settings + unless settings.is_a? Dry::Configurable::Settings + raise ArgumentError, "settings must be a Dry::Configurable::Settings" + end + settings.each do |setting| self << setting end From 25d76211f4d9c186ca95f517f061fba931beb9f7 Mon Sep 17 00:00:00 2001 From: Sean Gregory Date: Sun, 4 Jul 2021 09:58:32 -0400 Subject: [PATCH 03/15] remove whitespace --- lib/dry/configurable/settings.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/dry/configurable/settings.rb b/lib/dry/configurable/settings.rb index c4910ffe..84c57e21 100644 --- a/lib/dry/configurable/settings.rb +++ b/lib/dry/configurable/settings.rb @@ -27,7 +27,7 @@ def replace(settings) unless settings.is_a? Dry::Configurable::Settings raise ArgumentError, "settings must be a Dry::Configurable::Settings" end - + settings.each do |setting| self << setting end From b4c6371a3991889ca40bb1fd28869862c192b787 Mon Sep 17 00:00:00 2001 From: Sean Gregory Date: Tue, 20 Jul 2021 07:00:35 -0400 Subject: [PATCH 04/15] rubocop fixes --- Gemfile | 10 +++++----- Rakefile | 4 ++-- bin/console | 8 ++++---- .../dry/configurable/setting_spec.rb | 20 +++++++++---------- 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/Gemfile b/Gemfile index 0ccff33a..2ef950b4 100644 --- a/Gemfile +++ b/Gemfile @@ -1,16 +1,16 @@ # frozen_string_literal: true -source 'https://rubygems.org' +source "https://rubygems.org" -eval_gemfile 'Gemfile.devtools' +eval_gemfile "Gemfile.devtools" gemspec group :benchmarks do - gem 'benchmark-ips' + gem "benchmark-ips" end group :tools do - gem 'hotch' - gem 'pry-byebug', platform: :mri + gem "hotch" + gem "pry-byebug", platform: :mri end diff --git a/Rakefile b/Rakefile index ad52f833..be26d08b 100644 --- a/Rakefile +++ b/Rakefile @@ -1,8 +1,8 @@ # frozen_string_literal: true -require 'rspec/core/rake_task' +require "rspec/core/rake_task" -desc 'Run all specs in spec directory' +desc "Run all specs in spec directory" RSpec::Core::RakeTask.new(:spec) task default: :spec diff --git a/bin/console b/bin/console index 936f50ef..0afe5714 100755 --- a/bin/console +++ b/bin/console @@ -1,13 +1,13 @@ #!/usr/bin/env ruby # frozen_string_literal: true -require 'bundler/setup' -require 'dry/configurable' +require "bundler/setup" +require "dry/configurable" begin - require 'pry-byebug' + require "pry-byebug" Pry.start rescue LoadError - require 'irb' + require "irb" IRB.start end diff --git a/spec/integration/dry/configurable/setting_spec.rb b/spec/integration/dry/configurable/setting_spec.rb index 5d7a3ebc..8a72775b 100644 --- a/spec/integration/dry/configurable/setting_spec.rb +++ b/spec/integration/dry/configurable/setting_spec.rb @@ -185,14 +185,14 @@ include_context "configurable behavior" - context "can be configured with another class's settings" do - let(:other_klass) do - Class.new do + context "can be configured with another class's settings" do + let(:other_klass) do + Class.new do extend Dry::Configurable end end - it "replaces with each" do + it "replaces with each" do klass.setting :hello, "world" klass._settings.each do |setting| other_klass._settings << setting.dup @@ -200,24 +200,24 @@ expect(other_klass.config.hello).to eql("world") end - it "replaces with replace" do - klass.setting :hello, "world" + it "replaces with replace" do + klass.setting :hello, "world" other_klass._settings.replace(klass._settings.dup) expect(other_klass.config.hello).to eql("world") end - it "deep replace" do + it "deep replace" do klass.setting :database do setting :dsn, "localhost" end other_klass._settings.replace(klass._settings.dup) - expect(other_klass.config.database.dsn).to eql('localhost') + expect(other_klass.config.database.dsn).to eql("localhost") end - it "throws an error if the settings aren't Dry::Configurable::Settings" do + it "throws an error if the settings aren't Dry::Configurable::Settings" do klass.setting :hello, "world" - expect{ other_klass._settings.replace(klass) }.to raise_error do |error| + expect { other_klass._settings.replace(klass) }.to raise_error do |error| expect(error.class).to be(ArgumentError) end end From f2cc0334bc41358f0db4c5bceedc01cecb28e1a9 Mon Sep 17 00:00:00 2001 From: Sean Gregory Date: Tue, 20 Jul 2021 08:38:11 -0400 Subject: [PATCH 05/15] attempt at merge --- lib/dry/configurable/setting.rb | 5 ++++ lib/dry/configurable/settings.rb | 14 +++++++++++ .../dry/configurable/setting_spec.rb | 24 +++++++++++++++++++ 3 files changed, 43 insertions(+) diff --git a/lib/dry/configurable/setting.rb b/lib/dry/configurable/setting.rb index dd36f023..c4e23dbf 100644 --- a/lib/dry/configurable/setting.rb +++ b/lib/dry/configurable/setting.rb @@ -69,6 +69,11 @@ def initialize(name, input: Undefined, default: Undefined, **options) evaluate if input_defined? end + def merge(setting) + input.merge(setting.input) if input_defined? + evaluate + end + # @api private def input_defined? !input.equal?(Undefined) diff --git a/lib/dry/configurable/settings.rb b/lib/dry/configurable/settings.rb index 84c57e21..d316dd12 100644 --- a/lib/dry/configurable/settings.rb +++ b/lib/dry/configurable/settings.rb @@ -33,6 +33,20 @@ def replace(settings) end end + def merge(settings) + settings.each do |setting| + merge_setting(setting) + end + end + + def merge_setting(setting) + if key?(setting.name) + elements[setting.name].merge(setting) + else + self << setting + end + end + # @api private def <<(setting) elements[setting.name] = setting diff --git a/spec/integration/dry/configurable/setting_spec.rb b/spec/integration/dry/configurable/setting_spec.rb index 8a72775b..f2cce0f2 100644 --- a/spec/integration/dry/configurable/setting_spec.rb +++ b/spec/integration/dry/configurable/setting_spec.rb @@ -192,6 +192,30 @@ end end + it "should deep merge" do + klass.setting :database do + setting :type, "postgresql" + setting :host, "remote" + setting :port, 12_345 + setting :deep do + setting :one, 1 + setting :two, 2 + end + end + + other_klass.setting :database do + setting :host, "localhost" + setting :port + setting :deep, 3 + end + + other_klass._settings.merge(klass._settings.dup) + expect(other_klass.config.database.host).to eql("localhost") + expect(other_klass.config.database.port).to eql(nil) + expect(other_klass.config.database.type).to eql("postgresql") + expect(other_klass.config.database.deep).to eql(3) + end + it "replaces with each" do klass.setting :hello, "world" klass._settings.each do |setting| From c8853d89744d7acd808e15827244b194ce9fd49f Mon Sep 17 00:00:00 2001 From: Sean Gregory Date: Tue, 20 Jul 2021 19:30:35 -0400 Subject: [PATCH 06/15] merge settings --- lib/dry/configurable/settings.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/dry/configurable/settings.rb b/lib/dry/configurable/settings.rb index d316dd12..b476cc1d 100644 --- a/lib/dry/configurable/settings.rb +++ b/lib/dry/configurable/settings.rb @@ -34,11 +34,15 @@ def replace(settings) end def merge(settings) + unless settings.is_a? Dry::Configurable::Settings + raise ArgumentError, "settings must be a Dry::Configurable::Settings" + end settings.each do |setting| merge_setting(setting) end end + # @api private def merge_setting(setting) if key?(setting.name) elements[setting.name].merge(setting) From acf53fdec3ad077c567810ccb0cd698d173a1a4f Mon Sep 17 00:00:00 2001 From: Sean Gregory Date: Tue, 20 Jul 2021 19:34:58 -0400 Subject: [PATCH 07/15] empty line after guard clause --- lib/dry/configurable/settings.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/dry/configurable/settings.rb b/lib/dry/configurable/settings.rb index b476cc1d..4b489b59 100644 --- a/lib/dry/configurable/settings.rb +++ b/lib/dry/configurable/settings.rb @@ -37,6 +37,7 @@ def merge(settings) unless settings.is_a? Dry::Configurable::Settings raise ArgumentError, "settings must be a Dry::Configurable::Settings" end + settings.each do |setting| merge_setting(setting) end From 2e435c1acf0fae9d352eee5f28a22f4b25a1ce06 Mon Sep 17 00:00:00 2001 From: Sean Gregory Date: Tue, 20 Jul 2021 19:40:14 -0400 Subject: [PATCH 08/15] trailing whitespace --- lib/dry/configurable/settings.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/dry/configurable/settings.rb b/lib/dry/configurable/settings.rb index 4b489b59..5c1c93a4 100644 --- a/lib/dry/configurable/settings.rb +++ b/lib/dry/configurable/settings.rb @@ -37,7 +37,7 @@ def merge(settings) unless settings.is_a? Dry::Configurable::Settings raise ArgumentError, "settings must be a Dry::Configurable::Settings" end - + settings.each do |setting| merge_setting(setting) end From 58adf9bc8c57fea3d8179dae85b09f1f5215a85b Mon Sep 17 00:00:00 2001 From: Sean Gregory Date: Thu, 22 Jul 2021 19:35:35 -0400 Subject: [PATCH 09/15] remove replace, add Settings#merge, and Settings#merge! --- lib/dry/configurable/setting.rb | 10 +-- lib/dry/configurable/settings.rb | 39 ++++---- .../dry/configurable/setting_spec.rb | 62 ------------- .../dry/configurable/settings_spec.rb | 89 +++++++++++++++++++ 4 files changed, 113 insertions(+), 87 deletions(-) create mode 100644 spec/integration/dry/configurable/settings_spec.rb diff --git a/lib/dry/configurable/setting.rb b/lib/dry/configurable/setting.rb index c4e23dbf..dfe19552 100644 --- a/lib/dry/configurable/setting.rb +++ b/lib/dry/configurable/setting.rb @@ -42,6 +42,11 @@ class Setting class Nested < Setting CONSTRUCTOR = Config.method(:new) + def merge(setting) + settings = input.merge(setting.input) + Nested.new(name, input: settings, **options) + end + # @api private def pristine with(input: input.pristine) @@ -69,11 +74,6 @@ def initialize(name, input: Undefined, default: Undefined, **options) evaluate if input_defined? end - def merge(setting) - input.merge(setting.input) if input_defined? - evaluate - end - # @api private def input_defined? !input.equal?(Undefined) diff --git a/lib/dry/configurable/settings.rb b/lib/dry/configurable/settings.rb index 5c1c93a4..d8a2dc41 100644 --- a/lib/dry/configurable/settings.rb +++ b/lib/dry/configurable/settings.rb @@ -23,32 +23,17 @@ def initialize(elements = EMPTY_ARRAY) initialize_elements(elements) end - def replace(settings) - unless settings.is_a? Dry::Configurable::Settings - raise ArgumentError, "settings must be a Dry::Configurable::Settings" - end - - settings.each do |setting| + def merge!(settings) + merge(settings).each do |setting| self << setting end end def merge(settings) - unless settings.is_a? Dry::Configurable::Settings - raise ArgumentError, "settings must be a Dry::Configurable::Settings" - end + ensure_arguments(settings) - settings.each do |setting| - merge_setting(setting) - end - end - - # @api private - def merge_setting(setting) - if key?(setting.name) - elements[setting.name].merge(setting) - else - self << setting + settings.dup.inject(dup) do |memo, setting| + memo << merge_setting(setting) end end @@ -85,6 +70,20 @@ def pristine private + def merge_setting(setting) + if elements[setting.name].is_a? Setting::Nested + elements[setting.name].merge(setting) + else + setting + end + end + + def ensure_arguments(settings) + unless settings.is_a? Dry::Configurable::Settings + raise ArgumentError, "settings must be a Dry::Configurable::Settings" + end + end + # @api private def initialize_copy(source) initialize_elements(source.map(&:dup)) diff --git a/spec/integration/dry/configurable/setting_spec.rb b/spec/integration/dry/configurable/setting_spec.rb index f2cce0f2..cb981120 100644 --- a/spec/integration/dry/configurable/setting_spec.rb +++ b/spec/integration/dry/configurable/setting_spec.rb @@ -185,68 +185,6 @@ include_context "configurable behavior" - context "can be configured with another class's settings" do - let(:other_klass) do - Class.new do - extend Dry::Configurable - end - end - - it "should deep merge" do - klass.setting :database do - setting :type, "postgresql" - setting :host, "remote" - setting :port, 12_345 - setting :deep do - setting :one, 1 - setting :two, 2 - end - end - - other_klass.setting :database do - setting :host, "localhost" - setting :port - setting :deep, 3 - end - - other_klass._settings.merge(klass._settings.dup) - expect(other_klass.config.database.host).to eql("localhost") - expect(other_klass.config.database.port).to eql(nil) - expect(other_klass.config.database.type).to eql("postgresql") - expect(other_klass.config.database.deep).to eql(3) - end - - it "replaces with each" do - klass.setting :hello, "world" - klass._settings.each do |setting| - other_klass._settings << setting.dup - end - expect(other_klass.config.hello).to eql("world") - end - - it "replaces with replace" do - klass.setting :hello, "world" - other_klass._settings.replace(klass._settings.dup) - expect(other_klass.config.hello).to eql("world") - end - - it "deep replace" do - klass.setting :database do - setting :dsn, "localhost" - end - - other_klass._settings.replace(klass._settings.dup) - expect(other_klass.config.database.dsn).to eql("localhost") - end - - it "throws an error if the settings aren't Dry::Configurable::Settings" do - klass.setting :hello, "world" - expect { other_klass._settings.replace(klass) }.to raise_error do |error| - expect(error.class).to be(ArgumentError) - end - end - end - context "with a subclass" do let(:subclass) do Class.new(klass) diff --git a/spec/integration/dry/configurable/settings_spec.rb b/spec/integration/dry/configurable/settings_spec.rb new file mode 100644 index 00000000..2dd6471c --- /dev/null +++ b/spec/integration/dry/configurable/settings_spec.rb @@ -0,0 +1,89 @@ +# frozen_string_literal: true + +require "pathname" + +RSpec.describe Dry::Configurable::Settings do + context "can be configured with another class's settings" do + let(:klass) do + Class.new do + extend Dry::Configurable + end + end + + context "with merge" do + let(:other_klass) do + Class.new do + extend Dry::Configurable + end + end + + it "should override fields and return a Dry::Configurable::Settings" do + klass.setting :database do + setting :type, "postgresql" + setting :host, "remote" + end + + other_klass.setting :database do + setting :host, "localhost" + setting :port, 54_321 + end + + settings = other_klass._settings.merge(klass._settings) + + aggregate_failures do + expect(settings.class).to be(Dry::Configurable::Settings) + expect(settings[:database].input.entries.size).to eql(3) + expect(settings[:database].input[:type].default).to eql("postgresql") + expect(settings[:database].input[:host].default).to eql("remote") + expect(settings[:database].input[:port].default).to eql(54_321) + end + + aggregate_failures do + expect(other_klass.config.database.host).to eql("localhost") + expect(other_klass.config.database.port).to eql(54_321) + expect { other_klass.config.database.type }.to raise_error do |error| + expect(error.class).to eql(NoMethodError) + end + end + + aggregate_failures do + expect(klass.config.database.host).to eql("remote") + expect(klass.config.database.type).to eql("postgresql") + expect { klass.config.database.port }.to raise_error do |error| + expect(error.class).to eql(NoMethodError) + end + end + end + end + + context "with merge!" do + let(:other_klass) do + Class.new do + extend Dry::Configurable + end + end + + it "replaces undefined fields" do + klass.setting :hello, "world" + other_klass._settings.merge!(klass._settings) + expect(other_klass.config.hello).to eql("world") + end + + it "replaces deep fields" do + klass.setting :database do + setting :dsn, "localhost" + end + + other_klass._settings.merge!(klass._settings) + expect(other_klass.config.database.dsn).to eql("localhost") + end + + it "throws an error if the settings aren't Dry::Configurable::Settings" do + klass.setting :hello, "world" + expect { other_klass._settings.merge!(klass) }.to raise_error do |error| + expect(error.class).to be(ArgumentError) + end + end + end + end +end From bf1cb1bbb3d341cc343293d1d4ec84edc8badf03 Mon Sep 17 00:00:00 2001 From: Sean Gregory Date: Thu, 22 Jul 2021 19:51:50 -0400 Subject: [PATCH 10/15] missing spec --- spec/integration/dry/configurable/settings_spec.rb | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/spec/integration/dry/configurable/settings_spec.rb b/spec/integration/dry/configurable/settings_spec.rb index 2dd6471c..550f158f 100644 --- a/spec/integration/dry/configurable/settings_spec.rb +++ b/spec/integration/dry/configurable/settings_spec.rb @@ -78,6 +78,17 @@ expect(other_klass.config.database.dsn).to eql("localhost") end + it "overrides deep fields" do + klass.setting :database do + setting :dsn, "localhost" + end + other_klass.setting :database do + setting :dsn, "remote" + end + other_klass._settings.merge!(klass._settings) + expect(other_klass.config.database.dsn).to eql("localhost") + end + it "throws an error if the settings aren't Dry::Configurable::Settings" do klass.setting :hello, "world" expect { other_klass._settings.merge!(klass) }.to raise_error do |error| From fb26421f07251069f17ab6487658fea3331a16a9 Mon Sep 17 00:00:00 2001 From: Sean Gregory Date: Thu, 22 Jul 2021 21:12:04 -0400 Subject: [PATCH 11/15] use target settings --- lib/dry/configurable/setting.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/dry/configurable/setting.rb b/lib/dry/configurable/setting.rb index dfe19552..e59268c8 100644 --- a/lib/dry/configurable/setting.rb +++ b/lib/dry/configurable/setting.rb @@ -44,7 +44,7 @@ class Nested < Setting def merge(setting) settings = input.merge(setting.input) - Nested.new(name, input: settings, **options) + Nested.new(name, input: settings, **setting.options) end # @api private From 06932b74927a2f95e7d84042691a3353f91961f8 Mon Sep 17 00:00:00 2001 From: Sean Gregory Date: Thu, 22 Jul 2021 21:12:32 -0400 Subject: [PATCH 12/15] failing tests when the config has been invoked --- .../dry/configurable/settings_spec.rb | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/spec/integration/dry/configurable/settings_spec.rb b/spec/integration/dry/configurable/settings_spec.rb index 550f158f..2e5d7039 100644 --- a/spec/integration/dry/configurable/settings_spec.rb +++ b/spec/integration/dry/configurable/settings_spec.rb @@ -63,6 +63,14 @@ end end + it "should override a block" do + klass.setting(:hello, "bar") { |w| w.chars.join("_") } + other_klass.setting(:hello, "fuzz") { |w| w.chars.join("-") } + expect(other_klass.config.hello).to eql("f-u-z-z") + other_klass._settings.merge!(klass._settings) + expect(other_klass.config.hello).to eql("b_a_r") + end + it "replaces undefined fields" do klass.setting :hello, "world" other_klass._settings.merge!(klass._settings) @@ -73,7 +81,6 @@ klass.setting :database do setting :dsn, "localhost" end - other_klass._settings.merge!(klass._settings) expect(other_klass.config.database.dsn).to eql("localhost") end @@ -89,6 +96,18 @@ expect(other_klass.config.database.dsn).to eql("localhost") end + it "should work when the config accessor has already be invoked" do + klass.setting :database do + setting :dsn, "localhost" + end + other_klass.setting :database do + setting :dsn, "remote" + end + expect(other_klass.config.database.dsn).to eql("remote") + other_klass._settings.merge!(klass._settings) + expect(other_klass.config.database.dsn).to eql("localhost") + end + it "throws an error if the settings aren't Dry::Configurable::Settings" do klass.setting :hello, "world" expect { other_klass._settings.merge!(klass) }.to raise_error do |error| From a153da9e5cd60db8815defbcfc5b2dc1f5d03407 Mon Sep 17 00:00:00 2001 From: Sean Gregory Date: Thu, 22 Jul 2021 22:12:23 -0400 Subject: [PATCH 13/15] merge non nested settings to nested settings --- lib/dry/configurable/settings.rb | 2 +- spec/integration/dry/configurable/settings_spec.rb | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/dry/configurable/settings.rb b/lib/dry/configurable/settings.rb index d8a2dc41..cb081fc1 100644 --- a/lib/dry/configurable/settings.rb +++ b/lib/dry/configurable/settings.rb @@ -71,7 +71,7 @@ def pristine private def merge_setting(setting) - if elements[setting.name].is_a? Setting::Nested + if elements[setting.name].is_a?(Setting::Nested) && setting.is_a?(Setting::Nested) elements[setting.name].merge(setting) else setting diff --git a/spec/integration/dry/configurable/settings_spec.rb b/spec/integration/dry/configurable/settings_spec.rb index 2e5d7039..6eefefb8 100644 --- a/spec/integration/dry/configurable/settings_spec.rb +++ b/spec/integration/dry/configurable/settings_spec.rb @@ -96,6 +96,15 @@ expect(other_klass.config.database.dsn).to eql("localhost") end + it "shouldn't blow up when merging a non nested setting to a nested setting" do + klass.setting :database, "hello" + other_klass.setting :database do + setting :dsn, "localhost" + end + other_klass._settings.merge!(klass._settings) + expect(other_klass.config.database).to eql("hello") + end + it "should work when the config accessor has already be invoked" do klass.setting :database do setting :dsn, "localhost" From 40423c591678018cc3fdd8874e924bcdaf89ef35 Mon Sep 17 00:00:00 2001 From: Sean Gregory Date: Thu, 22 Jul 2021 22:12:58 -0400 Subject: [PATCH 14/15] fix linting --- spec/integration/dry/configurable/settings_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/integration/dry/configurable/settings_spec.rb b/spec/integration/dry/configurable/settings_spec.rb index 6eefefb8..b95d94a9 100644 --- a/spec/integration/dry/configurable/settings_spec.rb +++ b/spec/integration/dry/configurable/settings_spec.rb @@ -96,7 +96,7 @@ expect(other_klass.config.database.dsn).to eql("localhost") end - it "shouldn't blow up when merging a non nested setting to a nested setting" do + it "shouldn't blow up when merging a non nested setting to a nested setting" do klass.setting :database, "hello" other_klass.setting :database do setting :dsn, "localhost" From 16238c93133c66c08fdcae965793b6f9f22534d9 Mon Sep 17 00:00:00 2001 From: Sean Gregory Date: Tue, 27 Jul 2021 08:30:48 -0400 Subject: [PATCH 15/15] add replace back --- lib/dry/configurable/settings.rb | 8 +++++++ .../dry/configurable/settings_spec.rb | 23 +++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/lib/dry/configurable/settings.rb b/lib/dry/configurable/settings.rb index cb081fc1..899809ec 100644 --- a/lib/dry/configurable/settings.rb +++ b/lib/dry/configurable/settings.rb @@ -23,6 +23,14 @@ def initialize(elements = EMPTY_ARRAY) initialize_elements(elements) end + def replace(settings) + ensure_arguments(settings) + + settings.dup.each do |setting| + self << setting + end + end + def merge!(settings) merge(settings).each do |setting| self << setting diff --git a/spec/integration/dry/configurable/settings_spec.rb b/spec/integration/dry/configurable/settings_spec.rb index b95d94a9..104595a2 100644 --- a/spec/integration/dry/configurable/settings_spec.rb +++ b/spec/integration/dry/configurable/settings_spec.rb @@ -10,6 +10,29 @@ end end + context "with replace" do + let(:other_klass) do + Class.new do + extend Dry::Configurable + end + end + + it "should replace nested fields" do + klass.setting :database do + setting :host, "localhost" + end + + other_klass.setting :database do + setting :type, "postgresql" + end + other_klass._settings.replace(klass._settings) + expect(other_klass.config.database.host).to eql("localhost") + expect { other_klass.config.database.type }.to raise_error do |error| + expect(error.class).to eql(NoMethodError) + end + end + end + context "with merge" do let(:other_klass) do Class.new do