From fd7e30429e936d8fe0ddc75b44be55ac167818c3 Mon Sep 17 00:00:00 2001 From: Nuzair46 Date: Thu, 24 Oct 2024 18:47:25 +0900 Subject: [PATCH 1/7] Added extra sources --- README.md | 10 ++++++++++ lib/config.rb | 5 ++++- lib/generators/config/templates/config.rb | 5 +++++ spec/config_spec.rb | 18 ++++++++++++++++++ spec/spec_helper.rb | 1 + 5 files changed, 38 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d979634c..de11685f 100644 --- a/README.md +++ b/README.md @@ -154,6 +154,16 @@ Example production environment config file: #{Rails.root}/config/environments/production.yml ``` +### Extra sources + +You can load extra sources from the config folder during initialization by setting the `extra_sources` configuration option. + +```ruby +Config.setup do |config| + config.extra_sources = ['extra_settings'] +end +``` + ### Developer specific config files If you want to have local settings, specific to your machine or development environment, you can use the following files, which are automatically `.gitignore` : diff --git a/lib/config.rb b/lib/config.rb index e98d1e70..a8de23aa 100644 --- a/lib/config.rb +++ b/lib/config.rb @@ -29,7 +29,8 @@ module Config merge_hash_arrays: false, validation_contract: nil, evaluate_erb_in_yaml: true, - environment: nil + environment: nil, + extra_sources: [] ) def self.setup @@ -63,6 +64,7 @@ def self.load_and_set_settings(*sources) def self.setting_files(config_root, env) [ File.join(config_root, "#{Config.file_name}.yml").to_s, + *Config.extra_sources.map { |source| File.join(config_root, "#{source}.yml") }, File.join(config_root, Config.dir_name, "#{env}.yml").to_s, File.join(config_root, 'environments', "#{env}.yml").to_s, *local_setting_files(config_root, env) @@ -72,6 +74,7 @@ def self.setting_files(config_root, env) def self.local_setting_files(config_root, env) [ (File.join(config_root, "#{Config.file_name}.local.yml").to_s if env != 'test'), + *Config.extra_sources.map { |source| File.join(config_root, "#{source}.local.yml") }, File.join(config_root, Config.dir_name, "#{env}.local.yml").to_s, File.join(config_root, 'environments', "#{env}.local.yml").to_s ].compact diff --git a/lib/generators/config/templates/config.rb b/lib/generators/config/templates/config.rb index f6a222d0..02f0de9b 100644 --- a/lib/generators/config/templates/config.rb +++ b/lib/generators/config/templates/config.rb @@ -65,4 +65,9 @@ # # config.file_name = 'settings' # config.dir_name = 'settings' + + # Extra sources to load + # Loads extra sources from config folder + # + # config.extra_sources = ['extra_settings'] end diff --git a/spec/config_spec.rb b/spec/config_spec.rb index 505c6081..771c6061 100644 --- a/spec/config_spec.rb +++ b/spec/config_spec.rb @@ -38,6 +38,24 @@ expect(config.root['google.com']).to eq(3) end + it "should get load extra_sources files" do + Config.setup do |config| + config.extra_sources = ['settings2'] + end + + config = Config.setting_files("root/config", "staging") + expect(config).to eq([ + 'root/config/settings.yml', + 'root/config/settings2.yml', + 'root/config/settings/staging.yml', + 'root/config/environments/staging.yml', + 'root/config/settings.local.yml', + 'root/config/settings2.local.yml', + 'root/config/settings/staging.local.yml', + 'root/config/environments/staging.local.yml' + ]) + end + it "should load 2 basic config files" do config = Config.load_files("#{fixture_path}/settings.yml", "#{fixture_path}/settings2.yml") expect(config.size).to eq(1) diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index ca0739e7..554223b2 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -87,6 +87,7 @@ def self.reset self.fail_on_missing = false self.file_name = 'settings' self.dir_name = 'settings' + self.extra_sources = [] instance_variable_set(:@_ran_once, false) end end From cfd5a41b6aaf243f1aca05dbdae799330ada24ef Mon Sep 17 00:00:00 2001 From: Nuzair46 Date: Thu, 24 Oct 2024 18:55:36 +0900 Subject: [PATCH 2/7] add more info in readme --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index de11685f..4e5c2714 100644 --- a/README.md +++ b/README.md @@ -164,6 +164,8 @@ Config.setup do |config| end ``` +This will also overwrite the same config entries from the main file. + ### Developer specific config files If you want to have local settings, specific to your machine or development environment, you can use the following files, which are automatically `.gitignore` : From b0f45ff24e914e607b767538b59439d7e4850a6a Mon Sep 17 00:00:00 2001 From: Nuzair46 Date: Thu, 24 Oct 2024 18:56:16 +0900 Subject: [PATCH 3/7] fix typo --- spec/config_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/config_spec.rb b/spec/config_spec.rb index 771c6061..95517d7c 100644 --- a/spec/config_spec.rb +++ b/spec/config_spec.rb @@ -38,7 +38,7 @@ expect(config.root['google.com']).to eq(3) end - it "should get load extra_sources files" do + it "should load extra_sources files" do Config.setup do |config| config.extra_sources = ['settings2'] end From 7f97332fd6e33b16dd496d5b3ca52e7a591489ed Mon Sep 17 00:00:00 2001 From: Nuzair46 Date: Thu, 24 Oct 2024 18:57:09 +0900 Subject: [PATCH 4/7] fix template comment --- lib/generators/config/templates/config.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/generators/config/templates/config.rb b/lib/generators/config/templates/config.rb index 02f0de9b..9614f267 100644 --- a/lib/generators/config/templates/config.rb +++ b/lib/generators/config/templates/config.rb @@ -66,8 +66,7 @@ # config.file_name = 'settings' # config.dir_name = 'settings' - # Extra sources to load - # Loads extra sources from config folder + # Load extra sources from config folder # # config.extra_sources = ['extra_settings'] end From 0c3fd45e6a9a835f0b4aaafa5a639220589f28d5 Mon Sep 17 00:00:00 2001 From: Nuzair46 Date: Tue, 8 Jul 2025 23:27:49 +0900 Subject: [PATCH 5/7] Extra sources implemented same as main source --- README.md | 8 ++++-- lib/config.rb | 7 ++--- lib/generators/config/templates/config.rb | 9 +++++-- spec/config_spec.rb | 32 ++++++++++++++--------- 4 files changed, 36 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 4e5c2714..efea9fa9 100644 --- a/README.md +++ b/README.md @@ -156,11 +156,15 @@ Example production environment config file: ### Extra sources -You can load extra sources from the config folder during initialization by setting the `extra_sources` configuration option. +You can load extra sources during initialization by setting the `extra_sources` configuration option. ```ruby Config.setup do |config| - config.extra_sources = ['extra_settings'] + config.extra_sources = [ + 'path/to/extra_source.yml', # String: loads extra_source.yml + { api_key: ENV['API_KEY'] }, # Hash: direct hash source + MyCustomSource.new, # Object: custom source object that responds to `load` + ] end ``` diff --git a/lib/config.rb b/lib/config.rb index a8de23aa..1d9d7207 100644 --- a/lib/config.rb +++ b/lib/config.rb @@ -58,13 +58,15 @@ def self.load_files(*sources) def self.load_and_set_settings(*sources) name = Config.const_name Object.send(:remove_const, name) if Object.const_defined?(name) - Object.const_set(name, Config.load_files(sources)) + + # Include extra sources in the loading process + all_sources = [sources, Config.extra_sources].flatten.compact + Object.const_set(name, Config.load_files(*all_sources)) end def self.setting_files(config_root, env) [ File.join(config_root, "#{Config.file_name}.yml").to_s, - *Config.extra_sources.map { |source| File.join(config_root, "#{source}.yml") }, File.join(config_root, Config.dir_name, "#{env}.yml").to_s, File.join(config_root, 'environments', "#{env}.yml").to_s, *local_setting_files(config_root, env) @@ -74,7 +76,6 @@ def self.setting_files(config_root, env) def self.local_setting_files(config_root, env) [ (File.join(config_root, "#{Config.file_name}.local.yml").to_s if env != 'test'), - *Config.extra_sources.map { |source| File.join(config_root, "#{source}.local.yml") }, File.join(config_root, Config.dir_name, "#{env}.local.yml").to_s, File.join(config_root, 'environments', "#{env}.local.yml").to_s ].compact diff --git a/lib/generators/config/templates/config.rb b/lib/generators/config/templates/config.rb index 9614f267..ddd591da 100644 --- a/lib/generators/config/templates/config.rb +++ b/lib/generators/config/templates/config.rb @@ -66,7 +66,12 @@ # config.file_name = 'settings' # config.dir_name = 'settings' - # Load extra sources from config folder + # Load extra sources from a path. These can be file paths (strings), + # hashes, or custom source objects that respond to 'load' # - # config.extra_sources = ['extra_settings'] + # config.extra_sources = [ + # 'path/to/extra_source.yml', # String: loads extra_source.yml + # { api_key: ENV['API_KEY'] }, # Hash: direct hash source + # MyCustomSource.new, # Custom source object + # ] end diff --git a/spec/config_spec.rb b/spec/config_spec.rb index 95517d7c..79f8c4e2 100644 --- a/spec/config_spec.rb +++ b/spec/config_spec.rb @@ -38,22 +38,28 @@ expect(config.root['google.com']).to eq(3) end - it "should load extra_sources files" do + it "should load extra_sources and support different types" do + test_hash = { 'extra_key' => 'extra_value' } + object_source = double 'source' + + allow(object_source).to receive(:load) do + { 'server' => 'google.com' } + end + Config.setup do |config| - config.extra_sources = ['settings2'] + config.extra_sources = [ + "#{fixture_path}/settings2.yml", + test_hash, + object_source + ] end - config = Config.setting_files("root/config", "staging") - expect(config).to eq([ - 'root/config/settings.yml', - 'root/config/settings2.yml', - 'root/config/settings/staging.yml', - 'root/config/environments/staging.yml', - 'root/config/settings.local.yml', - 'root/config/settings2.local.yml', - 'root/config/settings/staging.local.yml', - 'root/config/environments/staging.local.yml' - ]) + Config.load_and_set_settings("#{fixture_path}/settings.yml") + + expect(Settings.size).to eq(1) + expect(Settings.extra_key).to eq('extra_value') + expect(Settings.another).to eq("something") + expect(Settings.server).to eq('google.com') end it "should load 2 basic config files" do From a4828922b1ce05b212814d3590426c1bfecc6251 Mon Sep 17 00:00:00 2001 From: Nuzair46 Date: Thu, 10 Jul 2025 09:34:57 +0900 Subject: [PATCH 6/7] fixed flaky double leakage --- gemfiles/rails_6.1.gemfile | 2 -- gemfiles/rails_7.0.gemfile | 2 -- spec/config_env_spec.rb | 6 +++++- spec/spec_helper.rb | 12 ++++++++++++ 4 files changed, 17 insertions(+), 5 deletions(-) diff --git a/gemfiles/rails_6.1.gemfile b/gemfiles/rails_6.1.gemfile index e54e2587..d601abdc 100644 --- a/gemfiles/rails_6.1.gemfile +++ b/gemfiles/rails_6.1.gemfile @@ -4,8 +4,6 @@ source "https://rubygems.org" gem "activerecord-jdbcsqlite3-adapter", "~> 61.1", platform: :jruby gem "bootsnap", ">= 1.4.4" -gem "drb", "~> 2.2" -gem "mutex_m", "~> 0.2.0" gem "rails", "6.1.7.10" gem "rspec-rails", "~> 5.0" gem "sqlite3", "~> 1.4", platform: :ruby diff --git a/gemfiles/rails_7.0.gemfile b/gemfiles/rails_7.0.gemfile index 8b4f31eb..c6ed52c7 100644 --- a/gemfiles/rails_7.0.gemfile +++ b/gemfiles/rails_7.0.gemfile @@ -5,8 +5,6 @@ source "https://rubygems.org" gem "activerecord-jdbcsqlite3-adapter", "~> 70.1", platform: :jruby gem "sqlite3", "~> 1.6.4", platform: :ruby gem "bootsnap", ">= 1.4.4" -gem "drb", "~> 2.2" -gem "mutex_m", "~> 0.2.0" gem "rails", "7.0.8.7" gem "rspec-rails", "~> 6.0.3" gem "sprockets-rails", "~> 3.4.2" diff --git a/spec/config_env_spec.rb b/spec/config_env_spec.rb index 99e3e863..5ca3109f 100644 --- a/spec/config_env_spec.rb +++ b/spec/config_env_spec.rb @@ -7,7 +7,11 @@ context 'when overriding settings via ENV variables is enabled' do let(:config) do - Config.load_files "#{fixture_path}/settings.yml", "#{fixture_path}/multilevel.yml" + config_instance = Config.load_files "#{fixture_path}/settings.yml", "#{fixture_path}/multilevel.yml" + # Ensure the Settings constant is set to the same instance for Config.reload! to work + Object.send(:remove_const, 'Settings') if Object.const_defined?('Settings') + Object.const_set('Settings', config_instance) + config_instance end after :all do diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 995a8d56..dda4923c 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -79,6 +79,18 @@ def fixture_path # Extend Config module with ability to reset configuration to the default values def self.reset + # Clear any existing Settings constant and its sources to prevent mock leakage + current_const_name = self.const_name + if Object.const_defined?(current_const_name) + settings_instance = Object.const_get(current_const_name) + # Clear the config sources to prevent mock doubles from leaking + if settings_instance.respond_to?(:instance_variable_set) + settings_instance.instance_variable_set(:@config_sources, []) + end + Object.send(:remove_const, current_const_name) + end + + # Reset configuration to defaults self.const_name = 'Settings' self.use_env = false self.knockout_prefix = nil From 25f7091586fdc3b7b4308cc6e3bef078528a4784 Mon Sep 17 00:00:00 2001 From: Nuzair46 Date: Fri, 11 Jul 2025 10:35:48 +0900 Subject: [PATCH 7/7] ci/fix jruby rails tests --- Appraisals | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Appraisals b/Appraisals index 82ef69fb..0734dbe6 100644 --- a/Appraisals +++ b/Appraisals @@ -52,9 +52,9 @@ if min_ruby_version.call('2.7') || RUBY_ENGINE != 'ruby' end # Rails 7.1 require Ruby > 2.7 -if min_ruby_version.call('2.7') && RUBY_ENGINE != 'jruby' +if min_ruby_version.call('2.7') appraise 'rails-7.1' do - gem 'activerecord-jdbcsqlite3-adapter', '~> 70.1', platform: :jruby + gem 'activerecord-jdbcsqlite3-adapter', '~> 71.0', platform: :jruby gem 'bootsnap', '>= 1.16.0' gem 'psych', '>= 4' gem 'rails', '~> 7.1.0' @@ -66,9 +66,9 @@ if min_ruby_version.call('2.7') && RUBY_ENGINE != 'jruby' end # Rails 7.2 requires Ruby > 3.1 -if min_ruby_version.call('3.1.0') && RUBY_ENGINE != 'jruby' +if min_ruby_version.call('3.1.0') appraise 'rails-7.2' do - gem 'activerecord-jdbcsqlite3-adapter', '~> 70.1', platform: :jruby + gem 'activerecord-jdbcsqlite3-adapter', '~> 71.0', platform: :jruby gem 'bootsnap', '>= 1.16.0' gem 'psych', '>= 4' gem 'rails', '~> 7.2.0' @@ -79,9 +79,9 @@ if min_ruby_version.call('3.1.0') && RUBY_ENGINE != 'jruby' end # Rails 8.0 requires Ruby > 3.2 -if min_ruby_version.call('3.2.0') && RUBY_ENGINE != 'jruby' +if min_ruby_version.call('3.2.0') appraise 'rails-8.0' do - gem 'activerecord-jdbcsqlite3-adapter', '~> 70.1', platform: :jruby + gem 'activerecord-jdbcsqlite3-adapter', '~> 71.0', platform: :jruby gem 'bootsnap', '>= 1.16.0' gem 'kamal', '~> 2.7.0' gem 'rails', '~> 8.0.0'