Blog

Thoughts from my daily grind

Configure Default URL Options on Rails

Posted by Ziyan Junaideen |Published: 07 January 2023 |Category: Marketing
Default Upload |

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.

Comments