Using the Rails router elsewhere

When working on Rails projects a commonly used part is the Rails router which is used to direct incoming requests to the appropriate controllers and actions and to generate paths and URLs so you don’t have to hardcode them all over the place.

In systems tests and integration tests the Rails router is also available for you to direct your tests to the appropriate URLs, in your regular tests or the Rails console however this is not the case. You can however get access to it by including a module that Rails can generate for you, if you call Rails.application.routes.url_helpers a module is returned that provides the Rails router’s methods.

When you call the Rails router’s methods outside of it’s regular context (in for example a model test or the Rails console) the methods that generate URLs will likely generate an ArgumentError to indicate that the host to link to is not known. If cannot get by with the methods that generate paths instead and really do need to generate a full URL you can set the default host to use like so:

Rails.application.routes.default_url_options[:host] = 'https://localhost:3000'

Rather than setting https://localhost:3000 you would of course set this to the host that you are using.

Below I will briefly demonstrate how to make use of what is described in this article in the Rails console with one of my own Rails projects:

$ bin/rails c
Loading development environment (Rails
[1] pry(main)> notes_path
NameError: undefined local variable or method `notes_path' for main:Object
from (pry):1:in `<main>'
[2] pry(main)> notes_url
NameError: undefined local variable or method `notes_url' for main:Object
from (pry):2:in `<main>'
[3] pry(main)> include Rails.application.routes.url_helpers
=> Object
[4] pry(main)> notes_path
=> "/notes"
[5] pry(main)> notes_url
ArgumentError: Missing host to link to! Please provide the :host parameter, set default_url_options[:host], or set :only_path to true
from /home/cor/.rbenv/versions/2.7.4/lib/ruby/gems/2.7.0/gems/actionpack- `full_url_for'
[6] pry(main)> Rails.application.routes.default_url_options[:host] = 'https://localhost:3000'
=> "https://localhost:3000"
[7] pry(main)> notes_url
=> "https://localhost:3000/notes"