85

I have a module with a function. It resides in /lib/contact.rb:

module Contact
  class << self
    def run(current_user)
      ...
    end
  end
end

I want to access the URL helpers like 'users_path' inside the module. How do I do that?

1

6 Answers 6

158

In your module, just perform a :

 include Rails.application.routes.url_helpers
Sign up to request clarification or add additional context in comments.

3 Comments

Doesn't work for me... :( could you give more details, please?
it should be noted that doing that include in a seperate class inside a rails application will erase existing initialized url_helpers causing the error : Missing host to link to! Please provide the :host parameter, set default_url_options[:host], or set :only_path to true
If you just need it once or twice, you can just use it directly inline, like Rails.application.routes.url_helpers.users_path. I find that more explicit and helpful to others reading your code.
36

Here is how I do it in any context without include

routes = Rails.application.routes.url_helpers
url = routes.some_path

That works in any context. If you're trying to include url_helpers - make sure you are doing that in the right place e.g. this works

module Contact
  class << self
    include Rails.application.routes.url_helpers
  end
end

and this does not work

module Contact
  include Rails.application.routes.url_helpers
  class << self
  end
end

One more example with Capybara tests

feature 'bla-bla' do
  include Rails.application.routes.url_helpers
  path = some_path #unknown local variable some_path
end

and now the right one

include Rails.application.routes.url_helpers
feature 'bla-bla' do
  path = some_path #this is ok
end

Comments

33

Delegation to url_helpers seems much better than including the whole module into your model

delegate :url_helpers, to: 'Rails.application.routes' 
url_helpers.users_url  => 'www.foo.com/users'

reference

3 Comments

should be url_helpers not url_helper, I think.
Hi there, how did you know it was Rails.application.routes that url_helpers should be delegated to? Where do you find this documentation? Thank you!
@NikSo api.rubyonrails.org is good place to start exploring. Here is documentation for URL helpers api.rubyonrails.org/classes/ActionController/UrlFor.html And including whole module seems overkill, delegation is better option but again its personal opinion :)
8

I've been struggling with the niceties the helper is expecting from the default controller and stack (default_url_options, etc.), and didn't want to hardcode the host.

Our URL helpers are provided by our nifty module, of course:

include Rails.application.routes.url_helpers

But include this as is, and (1) the helper is going to look for default_url_options, and (2) won't know about the request host nor the request.

The host part comes from the controller instance's url_options. Hence, I pass the controller context into my former module, now a class:

class ApplicationController
  def do_nifty_things
    HasAccessToRoutes.new(self).render
  end
end

class HasAccessToRoutes
  include Rails.application.routes.url_helpers
  delegate :default_url_options, :url_options, to: :@context

  def initialize(context)
    @context = context
  end

  def render
    nifty_things_url
  end
end

Might not fit every case, but it's been useful to me when implementing a sort of custom renderer.

In any way:

  • if you want access to the default url options seamlessly, or the host of the request, you need to pass controller/request context in
  • if you just need the path, no host, and don't care about the url options, you can just make some dummy methods.

Comments

3
delegate :url_helpers, to: 'Rails.application.routes' 
url_helpers.users_url  => 'www.foo.com/users'

to Augustin Riedinger, that delegation code needs to refer to url_helpers (plural), otherwise you get

undefined method `url_helper'

Comments

1

I think it's worth to mention in a separated answer the comment from Joshua Pinter above.

For a single use, a simple inline use like

Rails.application.routes.url_helpers.something_path

seems a good approach.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.