Skip to content

Commit b71895f

Browse files
krainboltgreenekaspth
authored andcommitted
First pass at settings file
1 parent a6cf649 commit b71895f

File tree

10 files changed

+62
-55
lines changed

10 files changed

+62
-55
lines changed

activerecord/lib/active_record/fixture_set/file.rb

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
# frozen_string_literal: true
22

3-
require "erb"
4-
require "yaml"
3+
require "active_support/configuration_file"
54

65
module ActiveRecord
76
class FixtureSet
@@ -51,24 +50,14 @@ def config_row
5150

5251
def raw_rows
5352
@raw_rows ||= begin
54-
data = YAML.load(render(IO.read(@file)))
53+
data = ActiveSupport::ConfigurationFile.parse(@file, context:
54+
ActiveRecord::FixtureSet::RenderContext.create_subclass.new.get_binding)
5555
data ? validate(data).to_a : []
56-
rescue ArgumentError, Psych::SyntaxError => error
57-
raise Fixture::FormatError, "a YAML error occurred parsing #{@file}. Please note that YAML must be consistently indented using spaces. Tabs are not allowed. Please have a look at https://www.yaml.org/faq.html\nThe exact error was:\n #{error.class}: #{error}", error.backtrace
56+
rescue RuntimeError => error
57+
raise Fixture::FormatError, error.message
5858
end
5959
end
6060

61-
def prepare_erb(content)
62-
erb = ERB.new(content)
63-
erb.filename = @file
64-
erb
65-
end
66-
67-
def render(content)
68-
context = ActiveRecord::FixtureSet::RenderContext.create_subclass.new
69-
prepare_erb(content).result(context.get_binding)
70-
end
71-
7261
# Validate our unmarshalled data.
7362
def validate(data)
7463
unless Hash === data || YAML::Omap === data

activerecord/lib/active_record/railties/databases.rake

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# frozen_string_literal: true
22

33
require "active_record"
4+
require "active_support/configuration_file"
45

56
databases = ActiveRecord::Tasks::DatabaseTasks.setup_initial_database_yaml
67

@@ -369,7 +370,7 @@ db_namespace = namespace :db do
369370
base_dir = ActiveRecord::Tasks::DatabaseTasks.fixtures_path
370371

371372
Dir["#{base_dir}/**/*.yml"].each do |file|
372-
if data = YAML.load(ERB.new(IO.read(file)).result)
373+
if data = ActiveSupport::ConfigurationFile.parse(file)
373374
data.each_key do |key|
374375
key_id = ActiveRecord::FixtureSet.identify(key)
375376

activerecord/test/cases/fixture_set/file_test.rb

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -137,12 +137,6 @@ def test_extracts_model_class_from_config_row
137137
end
138138
end
139139

140-
def test_erb_filename
141-
filename = "filename.yaml"
142-
erb = File.new(filename).send(:prepare_erb, "<% Rails.env %>\n")
143-
assert_equal erb.filename, filename
144-
end
145-
146140
private
147141
def tmp_yaml(name, contents)
148142
t = Tempfile.new name

activerecord/test/support/config.rb

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
# frozen_string_literal: true
22

3-
require "yaml"
4-
require "erb"
53
require "fileutils"
64
require "pathname"
5+
require "active_support/configuration_file"
76

87
module ARTest
98
class << self
@@ -21,8 +20,7 @@ def read_config
2120
FileUtils.cp TEST_ROOT + "/config.example.yml", config_file
2221
end
2322

24-
erb = ERB.new(config_file.read)
25-
expand_config(YAML.parse(erb.result(binding)).transform)
23+
expand_config ActiveSupport::ConfigurationFile.parse(config_file)
2624
end
2725

2826
def expand_config(config)

activestorage/lib/active_storage/engine.rb

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -106,17 +106,10 @@ class Engine < Rails::Engine # :nodoc:
106106
ActiveSupport.on_load(:active_storage_blob) do
107107
configs = Rails.configuration.active_storage.service_configurations ||=
108108
begin
109-
config_file = Pathname.new(Rails.root.join("config/storage.yml"))
109+
config_file = Rails.root.join("config/storage.yml")
110110
raise("Couldn't find Active Storage configuration in #{config_file}") unless config_file.exist?
111111

112-
require "yaml"
113-
require "erb"
114-
115-
YAML.load(ERB.new(config_file.read).result) || {}
116-
rescue Psych::SyntaxError => e
117-
raise "YAML syntax error occurred while parsing #{config_file}. " \
118-
"Please note that YAML must be consistently indented using spaces. Tabs are not allowed. " \
119-
"Error: #{e.message}"
112+
ActiveSupport::ConfigurationFile.parse(config_file)
120113
end
121114

122115
ActiveStorage::Blob.services = ActiveStorage::Service::Registry.new(configs)

activestorage/test/test_helper.rb

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
require "active_support/test_case"
99
require "active_support/core_ext/object/try"
1010
require "active_support/testing/autorun"
11+
require "active_support/configuration_file"
1112
require "active_storage/service/mirror_service"
1213
require "image_processing/mini_magick"
1314

@@ -23,11 +24,8 @@
2324
# Filter out the backtrace from minitest while preserving the one from other libraries.
2425
Minitest.backtrace_filter = Minitest::BacktraceFilter.new
2526

26-
require "yaml"
2727
SERVICE_CONFIGURATIONS = begin
28-
erb = ERB.new(Pathname.new(File.expand_path("service/configurations.yml", __dir__)).read)
29-
configuration = YAML.load(erb.result) || {}
30-
configuration.deep_symbolize_keys
28+
ActiveSupport::ConfigurationFile.parse(File.expand_path("service/configurations.yml", __dir__)).deep_symbolize_keys
3129
rescue Errno::ENOENT
3230
puts "Missing service configuration file in test/service/configurations.yml"
3331
{}

activesupport/lib/active_support.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ module ActiveSupport
3535

3636
autoload :Concern
3737
autoload :ActionableError
38+
autoload :ConfigurationFile
3839
autoload :CurrentAttributes
3940
autoload :Dependencies
4041
autoload :DescendantsTracker
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# frozen_string_literal: true
2+
3+
module ActiveSupport
4+
# Reads a YAML configuration file, evaluating any ERB, then
5+
# parsing the resulting YAML.
6+
#
7+
# Warns in case of YAML confusing characters, like invisible
8+
# non-breaking spaces.
9+
class ConfigurationFile # :nodoc:
10+
class FormatError < StandardError; end
11+
12+
def initialize(content_path)
13+
@content_path = content_path
14+
@content = read content_path
15+
end
16+
17+
def self.parse(content_path, **options)
18+
new(content_path).parse(**options)
19+
end
20+
21+
def parse(context: nil, **options)
22+
yaml = context ? ERB.new(@content).result(context) : ERB.new(@content).result
23+
YAML.load(yaml, **options) || {}
24+
rescue Psych::SyntaxError => error
25+
raise "YAML syntax error occurred while parsing #{@content_path}. " \
26+
"Please note that YAML must be consistently indented using spaces. Tabs are not allowed. " \
27+
"Error: #{error.message}"
28+
end
29+
30+
private
31+
def read(content_path)
32+
require "yaml"
33+
require "erb"
34+
35+
File.read(content_path).tap do |content|
36+
if content.match?(/\U+A0/)
37+
warn "File contains invisible non-breaking spaces, you may want to remove those"
38+
end
39+
end
40+
end
41+
end
42+
end

railties/lib/rails/application.rb

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
require "active_support/encrypted_configuration"
99
require "active_support/deprecation"
1010
require "active_support/hash_with_indifferent_access"
11+
require "active_support/configuration_file"
1112
require "rails/engine"
1213
require "rails/secrets"
1314

@@ -224,7 +225,7 @@ def config_for(name, env: Rails.env)
224225

225226
if yaml.exist?
226227
require "erb"
227-
all_configs = YAML.load(ERB.new(yaml.read).result, symbolize_names: true) || {}
228+
all_configs = ActiveSupport::ConfigurationFile.parse(yaml, symbolize_names: true)
228229
config, shared = all_configs[env.to_sym], all_configs[:shared]
229230

230231
if config.is_a?(Hash)
@@ -235,10 +236,6 @@ def config_for(name, env: Rails.env)
235236
else
236237
raise "Could not load configuration. No such file - #{yaml}"
237238
end
238-
rescue Psych::SyntaxError => error
239-
raise "YAML syntax error occurred while parsing #{yaml}. " \
240-
"Please note that YAML must be consistently indented using spaces. Tabs are not allowed. " \
241-
"Error: #{error.message}"
242239
end
243240

244241
# Stores some of the Rails initial environment parameters which

railties/lib/rails/application/configuration.rb

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
require "ipaddr"
44
require "active_support/core_ext/kernel/reporting"
55
require "active_support/file_update_checker"
6+
require "active_support/configuration_file"
67
require "rails/engine/configuration"
78
require "rails/source_annotation_extractor"
89

@@ -247,12 +248,9 @@ def database_configuration
247248
path = paths["config/database"].existent.first
248249
yaml = Pathname.new(path) if path
249250

250-
config = if yaml && yaml.exist?
251-
require "yaml"
252-
require "erb"
253-
loaded_yaml = YAML.load(ERB.new(yaml.read).result) || {}
254-
shared = loaded_yaml.delete("shared")
255-
if shared
251+
config = if yaml&.exist?
252+
loaded_yaml = ActiveSupport::ConfigurationFile.parse(yaml)
253+
if (shared = loaded_yaml.delete("shared"))
256254
loaded_yaml.each do |_k, values|
257255
values.reverse_merge!(shared)
258256
end
@@ -267,10 +265,6 @@ def database_configuration
267265
end
268266

269267
config
270-
rescue Psych::SyntaxError => e
271-
raise "YAML syntax error occurred while parsing #{paths["config/database"].first}. " \
272-
"Please note that YAML must be consistently indented using spaces. Tabs are not allowed. " \
273-
"Error: #{e.message}"
274268
rescue => e
275269
raise e, "Cannot load database configuration:\n#{e.message}", e.backtrace
276270
end

0 commit comments

Comments
 (0)