This one was a big aggravator to me lately. I have one controller that needs to call link_to and url_for, which are normally helper methods you'd call from a view. However, in this case during certain modifications to a record, I actually need to append user-visible HTML links to a block of HTML stored in that object, or possibly another one.
Specifically, I needed to put annotations in the description of a work order object that said, for example "this work order was escalated from Problem Report 293. This was done in a create action that redirected at the end and never rendered a view, so I really did need to generate that link in the controller. And for consistency with the rest of the application, I wanted to generate the link with link_to(@task).
Now, ActionView::Helpers::UrlHelper is not loaded in a Rails controller, even if you've put helper :all in application.rb (application_controller.rb in newer versions). So, when I tried to use link_to in the controller, I got an error:
NoMethodError: undefined method `link_to' for #
... etc ...
The first fix - but with a problem
A year ago, I fixed this just by adding
include ActionView::Helpers::UrlHelper at the top of that controller. This worked great ... for a while.
Lately, I've been rewriting this application into a RESTful style - it had previously been a controller/action style application. In the process, I started linking things with resource paths and polymorphic paths ... a lot of
link_to @task and
edit_polymorphic_path(@task) sorts of bits. And these started breaking. I began seeing this mysterious error:
You have a nil object when you didn't expect it!
The error occurred while evaluating nil.url_for
... some code here that calls a link_to ...
Trace of template inclusion: /tasks/_task_panel.html.erb, /tasks/_task_tabbed_panel.html.erb, /tasks/index.html.erb
Application Trace | Framework Trace | Full Trace
This one was a real bitch to debug, I have to say. The line in question that was failing in url_helper.rb said this:
url = @controller.send(:url_for, options). Clearly, @controller was nil ... which was very bizarre, because I never interact with that instance variable anywhere.
I thrashed around trying to find the cause of this error for quite some time. Eventually I realized that the link_to method was only failing when called from a view in TasksController, and not from any other controller. And then I realized that TasksController was the one where, a year ago, I'd put
include ActionView::Helpers::UrlHelper at the top. Somehow, including that helper in the controller was nullifying
@controller when those helper method we called from within the view. I removed the include and my polymorphic and resource links all started working again.
Now back to the original problem!
Of course, that then left me back with the problem I'd had a year ago ... needing to use link_to from within the controller and having no way to do it. After a fair bit of googling around I found this post from Neeraj, which had an interesting approach -- but a commenter had suggested a much easier solution:
I'm not certain where one would find this in the docs, but it does seem to have solved my problem for now. Onward and upward!