Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion config.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ Gem::Specification.new do |s|
s.require_paths = ['lib']
s.required_ruby_version = '>= 2.6.0'

s.add_dependency 'deep_merge', '~> 1.2', '>= 1.2.1'
s.add_dependency 'ostruct'

s.add_development_dependency 'rake', '~> 12.0', '>= 12.0.0'
Expand Down
1 change: 1 addition & 0 deletions gemfiles/sinatra.gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@
source "https://rubygems.org"

gem "sinatra", "2.0.8.1"
gem "deep_merge", "~> 1.2", ">= 1.2.1"

gemspec path: "../"
13 changes: 12 additions & 1 deletion lib/config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,18 @@
require 'config/sources/hash_source'
require 'config/sources/env_source'
require 'config/validation/schema'
require 'deep_merge/core'

begin
gem 'deep_merge', '~> 1.2', '>= 1.2.1'
require 'deep_merge/core'
rescue LoadError
Copy link
Member

@Nuzair46 Nuzair46 Jul 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think here like @pkuczynski said, it is better to raise an error if deep_merge is not available in a non Rails codebase. Since this gem is can be used in any ruby codebase, it is better to warn for Rails and raise error for non rails app if it is not available. Imo if ActiveSupport deep_merge cannot support all the features of this gem, it might not be worth modifying the code to disable those features. It might be worth keeping this dependency for better DX.

warn <<~WARNING
The `deep_merge` gem is not available. Trying to use ActiveSupport's Hash#deep_merge instead.
If you want to continue using 'deep_merge' gem, please add it to your Gemfile:
gem 'deep_merge', '~> 1.2', '>= 1.2.1'
WARNING
require 'active_support/core_ext/hash/deep_merge'
end

module Config
extend Config::Validation::Schema
Expand Down
44 changes: 26 additions & 18 deletions lib/config/options.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,19 @@ def reload!
if conf.empty?
conf = source_conf
else
DeepMerge.deep_merge!(
source_conf,
conf,
preserve_unmergeables: false,
knockout_prefix: Config.knockout_prefix,
overwrite_arrays: Config.overwrite_arrays,
merge_nil_values: Config.merge_nil_values,
merge_hash_arrays: Config.merge_hash_arrays
)
if defined?(DeepMerge)
DeepMerge.deep_merge!(
source_conf,
conf,
preserve_unmergeables: false,
knockout_prefix: Config.knockout_prefix,
overwrite_arrays: Config.overwrite_arrays,
merge_nil_values: Config.merge_nil_values,
merge_hash_arrays: Config.merge_hash_arrays
)
else
conf = conf.deep_merge!(source_conf)
end
end
end

Expand Down Expand Up @@ -98,15 +102,19 @@ def as_json(options = nil)

def merge!(hash)
current = to_hash
DeepMerge.deep_merge!(
hash.dup,
current,
preserve_unmergeables: false,
knockout_prefix: Config.knockout_prefix,
overwrite_arrays: Config.overwrite_arrays,
merge_nil_values: Config.merge_nil_values,
merge_hash_arrays: Config.merge_hash_arrays
)
if defined?(DeepMerge)
DeepMerge.deep_merge!(
hash.dup,
current,
preserve_unmergeables: false,
knockout_prefix: Config.knockout_prefix,
overwrite_arrays: Config.overwrite_arrays,
merge_nil_values: Config.merge_nil_values,
merge_hash_arrays: Config.merge_hash_arrays
)
else
current.deep_merge!(hash)
end
marshal_load(__convert(current).marshal_dump)
self
end
Expand Down
15 changes: 15 additions & 0 deletions spec/config_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,11 @@
end

it 'should not overwrite values with nil' do
unless defined?(DeepMerge)
skip <<~REASON
DeepMerge is not available in the current context. This test only applies when the `deep_merge` gem is available.
REASON
end
old_value = config.inner.something1
config.merge!(hash_with_nil)
expect(config.inner.something1).to eq(old_value)
Expand Down Expand Up @@ -418,6 +423,11 @@
end

it 'should remove elements from settings' do
unless defined?(DeepMerge)
skip <<~REASON
DeepMerge is not available in the current context. This test only applies when the `deep_merge` gem is available.
REASON
end
expect(config.array1).to eq(['item4', 'item5', 'item6'])
expect(config.array2.inner).to eq(['item4', 'item5', 'item6'])
expect(config.array3).to eq('')
Expand Down Expand Up @@ -474,6 +484,11 @@
end

it 'should merge arrays from multiple configs' do
unless defined?(DeepMerge)
skip <<~REASON
DeepMerge is not available in the current context. This test only applies when the `deep_merge` gem is available.
REASON
end
expect(config.arraylist1.size).to eq(6)
expect(config.arraylist2.inner.size).to eq(6)
end
Expand Down
35 changes: 35 additions & 0 deletions spec/options_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,11 @@
end

it 'should overwrite the previous values' do
unless defined?(DeepMerge)
skip <<~REASON
DeepMerge is not available in the current context. This test only applies when the `deep_merge` gem is available.
REASON
end
expect(config['tvrage']['service_url']).to eq('http://url2')
end

Expand All @@ -124,6 +129,11 @@
end

it 'should overwrite the previous values' do
unless defined?(DeepMerge)
skip <<~REASON
DeepMerge is not available in the current context. This test only applies when the `deep_merge` gem is available.
REASON
end
expect(config['tvrage']['service_url']).to eq('http://url3')
end
end
Expand All @@ -144,6 +154,11 @@
end

it 'should add keys from the added file' do
unless defined?(DeepMerge)
skip <<~REASON
DeepMerge is not available in the current context. This test only applies when the `deep_merge` gem is available.
REASON
end
expect(config['tvrage']['service_url']).to eq('http://services.tvrage.com')
end

Expand All @@ -154,6 +169,11 @@
end

it 'should overwrite the previous values' do
unless defined?(DeepMerge)
skip <<~REASON
DeepMerge is not available in the current context. This test only applies when the `deep_merge` gem is available.
REASON
end
expect(config['tvrage']['service_url']).to eq('http://services.tvrage.com')
end
end
Expand All @@ -168,6 +188,11 @@
end

it 'should be overwritten by the following values' do
unless defined?(DeepMerge)
skip <<~REASON
DeepMerge is not available in the current context. This test only applies when the `deep_merge` gem is available.
REASON
end
expect(config['tvrage']['service_url']).to eq('http://services.tvrage.com')
end

Expand Down Expand Up @@ -246,6 +271,11 @@
} }

it 'should merge the arrays' do
unless defined?(DeepMerge)
skip <<~REASON
DeepMerge is not available in the current context. This test only applies when the `deep_merge` gem is available.
REASON
end
config = Config.load_files("#{fixture_path}/deep_merge3/config1.yml", "#{fixture_path}/deep_merge3/config2.yml")

expect(config.array.length).to eq(1)
Expand All @@ -261,6 +291,11 @@
} }

it 'should merge the arrays' do
unless defined?(DeepMerge)
skip <<~REASON
DeepMerge is not available in the current context. This test only applies when the `deep_merge` gem is available.
REASON
end
config = Config.load_files("#{fixture_path}/deep_merge3/config1.yml", "#{fixture_path}/deep_merge3/config2.yml")

expect(config.array.length).to eq(2)
Expand Down