Configure Default URL Options on Rails
Ruby on Rails is a web framework. That means it has one job: to serve web content where URLs play an essential role. Yet, what I find so fascinating is the surprising lack of clarity around configuring default URL options in a Rails application and the fact that it is not available out of the box.
When not configured, we often encounter the Missing host link to
error.
> short_url(@short)
ArgumentError: Missing host to link to! Please provide the :host parameter, set default_url_options[:host], or set :only_path to true
from /Users/jdeen/.rvm/gems/ruby-3.1.2@edge-app/gems/actionpack-7.0.4/lib/action_dispatch/http/url.rb:64:in `full_url_for'
In an ideal world, a general default_url_options
would set up both action-mailer and routing with the option to override. But we don't live in a perfect world.
We have to set up two parts of the application with URL settings: namely action mailer and routes.
Configuration
Method 1: We can do this configuration in environment files. This is my preferred way of configuring default URL options as both the mail and route configurations are then available in the same file.
# config/environments/development.rb
Rails.application.configure do |config|
# ...
config.action_mailer.default_url_options = { host: 'jdeen.test' }
# ...
end
Rails.application.routes.default_url_options[:host] = 'jdeen.test'
I like to have them in the same place and prefer to have them in environment files.
Method 2: Default URL options configured in an initializer
# config/initializers/default_url_options.rb
hosts = {
development: 'jdeen.test',
staging: 'jdeen-staging.com',
production: 'jdeen.com'
}.freeze
Rails.application.routes.default_url_options[:host] = hosts[Rails.env.to_sym]
Method 3: The routes configuration can be done in config/routes.rb
file as well, should you prefer.
# config/routes.rb
# .
# ..
# ...
hosts = {
development: 'jdeen.test',
staging: 'jdeen-staging.com',
production: 'jdeen.com'
}.freeze
Rails.application.routes.default_url_options[:host] = hosts[Rails.env.to_sym]
Conclusion
The default_url_options
is one of the first confusing issues I experienced in Rails 3 ten years ago. Unfortunately, for some reason, the situation remains the same to this date. I wish the configuration were available as a single configuration with a fallback (ex: if we need to configure a different host for mailers).
# config/environments/development.rb
Rails.application.configure do |config|
# ...
config.default_url_options = { host: 'jdeen.test' }
# ...
end
Rails.application.routes.default_url_options[:host] = 'jdeen.test'
I can only hope. Maybe I am asking for too much 🤷♂️. Until then, adding this extra line somewhere is going to be one of the first tasks after running rails new
.
About the Author
Ziyan Junaideen -
Ziyan is an expert Ruby on Rails web developer with 8 years of experience specializing in SaaS applications. He spends his free time he writes blogs, drawing on his iPad, shoots photos.