draper: NoMethodError undefined method `host' for nil:NilClass (not in tests)

We’re getting an intermittent error with with a Draper decorator accessing any route.

Trying to access a route within the Decorate:

h.material_path(child.space, child)

Results in the error:

NoMethodError - undefined method `host' for nil:NilClass

Backtrace

[GEM_ROOT]/gems/actionpack-3.2.8/lib/action_controller/metal/url_for.rb:30url_options
[GEM_ROOT]/gems/actionpack-3.2.8/lib/action_view/helpers/url_helper.rb:37url_options
[GEM_ROOT]/gems/actionpack-3.2.8/lib/action_dispatch/routing/url_for.rb:148url_for
[GEM_ROOT]/gems/actionpack-3.2.8/lib/action_view/helpers/url_helper.rb:107url_for
[GEM_ROOT]/gems/actionpack-3.2.8/lib/action_dispatch/routing/route_set.rb:213material_path
[PROJECT_ROOT]/app/decorators/material_decorator.rb:16block in json_for_tree

Any request that access routes seems to cause this error, but only sometimes (20% of the time roughly). Other times it works as expected.

About this issue

  • Original URL
  • State: closed
  • Created 12 years ago
  • Comments: 49 (25 by maintainers)

Commits related to this issue

Most upvoted comments

Was this fixed? Or we just add?:

include Rails.application.routes.url_helpers

To our decorator classes in order to fix it?

If you’re invoking draper classes outside of a view/controller context (i.e. in a sidekiq worker), please see this for a fix https://github.com/drapergem/draper/issues/268#issuecomment-55512283

I think a few people have already touched on this but I think the core issue, as far as I understand, is that routing is not specific to the view_context.

If I understand correctly, draper is routing everything that is h.whatever through the view context. Perhaps there should be a r. helper that accesses the routing engine without the view context being present as there are many good use cases for draper outside of Rails views.

One example for us is within a Grape API, where we want to share some of our Rails routes. I don’t have a code solution for this, but I’m just throwing these thoughts out into the aether hoping it inspires somebody 😃

Try to put this in an initializer:

module Draper
  class HelperProxy
    include Rails.application.routes.url_helpers
    default_url_options[:host] = ::Rails.application.routes.default_url_options[:host]
  end
end

Make sure you have

routes.default_url_options = { host: "domain.com" }

in your environment/*.rb files.

happened again in 1.2.0. My app sent mail by sidekiq on background, and it finally render

    h.link_to(model.title, h.polymorphic_url(model))

and raise error as

Error Message: NoMethodError: undefined method `host’ for nil:NilClass Where: [PROJECT_ROOT]/vendor/bundle/ruby/1.9.1/gems/actionpack-3.2.12/lib/action_controller/metal/url_for.rb, line 30

when I grep the source of draper, I cant found ActionMailer::Base.default_url_options of @spectator fix. also check the build_strategy.rb, nothing about ActionMailer at all.