This article is a translated version of my original Japanese blog post: Railsでconfig/x
みたいなディレクトリ作るとymlが分かりやすくなる説.
Hello! In this post, I’ll share a simple yet effective way to organize configuration files in a Rails application.
As your Rails project grows, keeping your config/
directory clean and manageable becomes increasingly important.
We’ll explore how creating custom directories like config/x
and using config_for
can make your YAML configuration files easier to manage and maintain.
Table of Contents
- Leveraging
Rails.configuration
andconfig_for
for Custom Configurations
- Understanding
config.x.something
vsconfig.something
- The Problem: Too Many
config/*.yml
Files
- Why the default
config/
directory gets cluttered- The Solution: Organizing Custom App Settings with
config/x/*.yml
Leveraging Rails.configuration
and config_for
for Custom Configurations
First, let’s talk about Rails.configuration
and config_for
.
These features were introduced in Rails 4.2 as an alternative to gems like the config gem (nostalgic) or the settings_logic gem (also nostalgic).
Here’s an excerpt from the Rails 7.0 guide:
Rails.configuration
To set configurations, you define them in config/application.rb
or similar files:
config.x.payment_processing.schedule = :daily
config.x.payment_processing.retries = 3
config.super_debugger = true
You can retrieve these values from anywhere in your app like this:
Rails.configuration.x.payment_processing.schedule # => :daily
Rails.configuration.x.payment_processing.retries # => 3
Rails.configuration.x.payment_processing.not_set # => nil
Rails.configuration.super_debugger # => true
Now, about config_for
config_for
is a method for loading YAML files.
It’s often used to set values in Rails.configuration
.
For example, if you have a YAML file like this:
# config/payment.yml
production:
environment: production
merchant_id: production_merchant_id
public_key: production_public_key
private_key: production_private_key
development:
environment: sandbox
merchant_id: development_merchant_id
public_key: development_public_key
private_key: development_private_key
You can set these values in config/application.rb
as follows:
# config/application.rb
module MyApp
class Application < Rails::Application
config.payment = config_for(:payment)
end
end
In this case, you’d retrieve the values like this:
Rails.configuration.payment['merchant_id'] # => production_merchant_id or development_merchant_id
You can also set the value using config.x.payment = config_for(:payment)
if you prefer, like this:
# config/application.rb
module MyApp
class Application < Rails::Application
config.x.payment = config_for(:payment)
end
end
Then, you can retrieve the values like this:
Rails.configuration.x.payment['merchant_id'] # => production_merchant_id or development_merchant_id
What’s the difference between config.x.something
and config.something
?
From an implementation standpoint, the key difference is that config.x.something
allows for nesting.
# Example
config.x.payment_processing.schedule = :daily
Other than that, the Rails guide doesn’t suggest any major differences. However, I personally feel like adding x
gives it a custom, localized feel, kind of like custom HTTP headers.
The Problem: Too Many config/*.yml
Files
Whether you use x
or not, as you make use of these methods, you’ll end up with lots of YAML files in the config/
directory.
Here’s an example of what the config/
folder might look like:
application.rb
bar.yml
baz.yml
boot.rb
cable.yml
corge.yml
database.yml
environment.rb
environments/
foo.yml
fred.yml
garply.yml
grault.yml
initializers/
locales/
newrelic.yml
plugh.yml
puma.rb
quux.yml
qux.yml
routes.rb
sidekiq.yml
spring.rb
storage.yml
thud.yml
waldo.yml
webpack/
webpacker.yml
The mess
It’s not the sheer number of files that’s the problem. The issue is that it becomes difficult to distinguish between YAML files provided by Rails or third-party gems and your custom configurations.
For instance:
-
config/cable.yml
andconfig/database.yml
come from Rails. -
config/sidekiq.yml
comes from the sidekiq gem. -
config/newrelic.yml
comes from the New Relic gem. - All other
config/*.yml
files are custom app configurations set usingconfig_for
.
In summary, if we were to comment on the files in config/
, it might look like this:
config/
├── application.rb
├── database.yml # from Rails
├── cable.yml # from Rails
├── sidekiq.yml # from Sidekiq gem
├── newrelic.yml # from New Relic gem
├── bar.yml # custom app config
└── foo.yml # custom app config
Now compare that to a cleaner structure with config/x/
:
config/
├── application.rb
├── x/ # custom app configs live here
│ ├── bar.yml
│ └── foo.yml
├── database.yml
└── cable.yml
Even experienced developers can have a hard time distinguishing between these files at a glance.
The Solution: Organizing Custom App Settings with config/x/*.yml
Here’s my suggestion: config_for
can actually load files from directories other than config/
. This changed in Rails 5.0 (see the relevant commit here).
So, we could rewrite config/application.rb
like this:
# config/application.rb
module MyApp
class Application < Rails::Application
config.x.bar = config_for(Rails.root.join('config/x/bar.yml'))
config.x.baz = config_for(Rails.root.join('config/x/baz.yml'))
config.x.corge = config_for(Rails.root.join('config/x/corge.yml'))
# ...snip...
config.x.waldo = config_for(Rails.root.join('config/x/waldo.yml'))
end
end
By doing this, we can easily distinguish between YAML files provided by Rails or third-party gems and our custom configurations.
Here’s how the config/
folder would look:
# config/
application.rb
boot.rb
cable.yml # From Rails
database.yml # From Rails
environment.rb
environments/
initializers/
locales/
newrelic.yml # From New Relic gem
puma.rb
routes.rb
sidekiq.yml # From Sidekiq gem
spring.rb
storage.yml # From Rails
webpack/
webpacker.yml # From Rails
x/
And in config/x/
:
# config/x/
bar.yml # Custom for this Rails app
baz.yml # Custom for this Rails app
corge.yml # Custom for this Rails app
foo.yml # Custom for this Rails app
fred.yml # Custom for this Rails app
garply.yml # Custom for this Rails app
grault.yml # Custom for this Rails app
plugh.yml # Custom for this Rails app
quux.yml # Custom for this Rails app
qux.yml # Custom for this Rails app
thud.yml # Custom for this Rails app
waldo.yml # Custom for this Rails app
By separating the files like this, everything becomes much clearer!
Conclusion
In this post, we discussed how creating a config/x
directory can help you organize custom YAML configuration files more efficiently in Rails. By separating app-specific settings from third-party and framework-provided configurations, you not only make your codebase easier to manage, but also improve the clarity for developers who need to understand the system at a glance.
This structure encourages a cleaner, more modular approach, which is particularly beneficial for scaling and maintaining large Rails applications.
Top comments (0)