Rails routing outside views and controllers

We use Rails routing helpers in views and controllers but sometimes we need to generate a link from a service class or background job.

To get started, let’s assume that we have a post resources which provide us with this path helper:

posts_path  # "/posts"

We add the following simple service class:

class MyService
  include Rails.application.routes.url_helpers

  def generate_stuff
    posts_path
  end

end

To check the link generation, we can use Rails console:

MyService.new.generate_stuff   # "/posts"

I noticed in different projects that I need to use the URL helper instead of path helper. So we will edit the service as follows:

class MyService
  include Rails.application.routes.url_helpers

  def generate_stuff
    posts_url
  end

end

But we will get the following Error:

Missing host to link to! Please provide the :host parameter,set default_url_options[:host], or set :only_path to true

To fix it we need just to add a config for existing environments in our applications for example:

# development
# config/environments/development.rb
Rails.application.routes.default_url_options[:host] = 'localhost:3000'

# production
# config/environments/production.rb
Rails.application.routes.default_url_options[:host] = 'mysite.com'

You may say, that we don’t need this configuration when using URL helpers in views, right?

Absolutely, from Rails documentation for UrlFor method we can check:

By default, all controllers and views have access to a special version
of #url_for, that already knows what the current hostname is.
So if you use #url_for in your controllers or your views,
then you don’t need to explicitly pass the :host argument.

Reference

That’s it, have fun and keep coding 🙂