Allow non-hash values in config files

Fix: https://github.com/rails/rails/issues/37800
This commit is contained in:
Jean Boussier 2019-12-02 11:52:54 +01:00 committed by Kasper Timm Hansen
parent f2b69d80ab
commit 21c7199c0f
No known key found for this signature in database
GPG Key ID: 191153215EDA53D8
2 changed files with 35 additions and 22 deletions

@ -220,27 +220,25 @@ def message_verifier(verifier_name)
# config.middleware.use ExceptionNotifier, config_for(:exception_notification) # config.middleware.use ExceptionNotifier, config_for(:exception_notification)
# end # end
def config_for(name, env: Rails.env) def config_for(name, env: Rails.env)
if name.is_a?(Pathname) yaml = name.is_a?(Pathname) ? name : Pathname.new("#{paths["config"].existent.first}/#{name}.yml")
yaml = name
else
yaml = Pathname.new("#{paths["config"].existent.first}/#{name}.yml")
end
if yaml.exist? if yaml.exist?
require "erb" require "erb"
config = YAML.load(ERB.new(yaml.read).result, symbolize_names: true) || {} all_configs = YAML.load(ERB.new(yaml.read).result, symbolize_names: true) || {}
config = (config[:shared] || {}).deep_merge(config[env.to_sym] || {}) config, shared = all_configs[env.to_sym], all_configs[:shared]
ActiveSupport::OrderedOptions.new.tap do |options| if config.is_a?(Hash)
options.update(config) ActiveSupport::OrderedOptions.new.update(shared&.deep_merge(config) || config)
else
config || shared
end end
else else
raise "Could not load configuration. No such file - #{yaml}" raise "Could not load configuration. No such file - #{yaml}"
end end
rescue Psych::SyntaxError => e rescue Psych::SyntaxError => error
raise "YAML syntax error occurred while parsing #{yaml}. " \ raise "YAML syntax error occurred while parsing #{yaml}. " \
"Please note that YAML must be consistently indented using spaces. Tabs are not allowed. " \ "Please note that YAML must be consistently indented using spaces. Tabs are not allowed. " \
"Error: #{e.message}" "Error: #{error.message}"
end end
# Stores some of the Rails initial environment parameters which # Stores some of the Rails initial environment parameters which

@ -1958,6 +1958,22 @@ class D < C
assert_equal({ baz: 1 }, actual[:bar]) assert_equal({ baz: 1 }, actual[:bar])
end end
test "config_for does not assume config is a hash" do
app_file "config/custom.yml", <<~RUBY
development:
- foo
- bar
RUBY
add_to_config <<~RUBY
config.my_custom_config = config_for('custom')
RUBY
app "development"
assert_equal %w( foo bar ), Rails.application.config.my_custom_config
end
test "config_for uses the Pathname object if it is provided" do test "config_for uses the Pathname object if it is provided" do
app_file "config/custom.yml", <<-RUBY app_file "config/custom.yml", <<-RUBY
development: development:
@ -1985,19 +2001,19 @@ class D < C
assert_equal "Could not load configuration. No such file - #{app_path}/config/custom.yml", exception.message assert_equal "Could not load configuration. No such file - #{app_path}/config/custom.yml", exception.message
end end
test "config_for without the environment configured returns an empty hash" do test "config_for without the environment configured returns nil" do
app_file "config/custom.yml", <<-RUBY app_file "config/custom.yml", <<~RUBY
test: test:
key: 'custom key' key: 'custom key'
RUBY RUBY
add_to_config <<-RUBY add_to_config <<~RUBY
config.my_custom_config = config_for('custom') config.my_custom_config = config_for('custom')
RUBY RUBY
app "development" app "development"
assert_equal({}, Rails.application.config.my_custom_config) assert_nil Rails.application.config.my_custom_config
end end
test "config_for implements shared configuration as secrets case found" do test "config_for implements shared configuration as secrets case found" do
@ -2055,17 +2071,16 @@ class D < C
assert_equal({ baz: 1, qux: 2 }, Rails.application.config.my_custom_config[:foo][:bar]) assert_equal({ baz: 1, qux: 2 }, Rails.application.config.my_custom_config[:foo][:bar])
end end
test "config_for with empty file returns an empty hash" do test "config_for with empty file returns nil" do
app_file "config/custom.yml", <<-RUBY app_file "config/custom.yml", ""
RUBY
add_to_config <<-RUBY add_to_config <<~RUBY
config.my_custom_config = config_for('custom') config.my_custom_config = config_for('custom')
RUBY RUBY
app "development" app "development"
assert_equal({}, Rails.application.config.my_custom_config) assert_nil Rails.application.config.my_custom_config
end end
test "config_for containing ERB tags should evaluate" do test "config_for containing ERB tags should evaluate" do