如何在Rails控制器中混合并调用link_to?

59

这似乎是一个初学者问题,但简单的答案却让我不知所措。我需要在ActionController方法中调用link_to来生成一个HTML链接。ActionView::Helpers::UrlHelper.link_to会调用url_for,但它会调用AV模块的版本而不是控制器的版本。我设法通过添加

来强制实现我想要的效果。
  #FIXME there must be a better way to mixin link_to
  alias_method :self_url_for, :url_for
  include ActionView::Helpers::UrlHelper
  alias_method :url_for, :self_url_for
在控制器中,但我仍然不确定它为什么可以正常工作。请问有人能够解释一下这里发生的方法范围和隐藏吗?有没有更好的方式来混合使用link_to(或通常情况下,只包括一些模块中的方法),以便我可以在控制器中调用它(生成带有链接的flash字符串是用例)。
请不要谈MVC - 如果有什么的话,link_to应该在一个与url_for分开的模块中。从许多关于此的噪声来看,很多人遇到了这个看似微不足道的问题,并最终浪费了一个小时来按照“Rails方式”进行操作,而真正想要的是一个一分钟的hack,让我的应用程序立即工作。是否有一种使用helper的“Rails方式”来实现这一点?还是有更好的Ruby方式?
4个回答

118

兼容Rails 3、4和5:

view_context.link_to

8
现在应该将这个标记为正确答案。它也适用于 Rails 4。 - hoitomt
关于这个结构,html_safe怎么样?你能提供答案吗?谢谢 :) - mmike

74

这并不是真正回答你的问题,但有一个更简单的方法

对于Rails 5,使用helpers代理

helpers.link_to '...', '...'

Rails 3和4版本,由于你正在从控制器中使用帮助程序,因此可以使用view_context。

# in the controller code
view_context.link_to '...', '...'

# instead of using your mixin code 
link_to '...', '...'

对于Rails 2,由于你正在从控制器使用帮助程序,你实际上可以访问控制器的@template成员变量,@template是视图,已经混合了UrlHelper

# in the controller code
@template.link_to '...', '...'

# instead of using your mixin code 
link_to '...', '...'

如果你需要在控制器之外的代码中使用UrlHelper,那么你的解决方案可能就是这样。


5
我的控制器中@template为nil。有任何想法是为什么? - Tyler Collier
@TylerCollier - 也许随着Rails 3的出现情况发生了改变?在2版本上它是可以实现的。 - house9

0
你可以这样做:
ActionController.helpers.link_to("Click Me!", awesome_path)

但是,更好的生成链接的位置可能是在助手模块中,因为 UrlHelper 和其他与视图相关的助手已经包含在其中。

[更新]

这种方法已经过时,不再适用。


1
我从阅读这篇博客(http://blog.lrdesign.com/2009/05/using-link_to-or-other-helper-methods-in-a-controller/)学到了使用`self.class.helpers.link_to`,但 ActionController.helpers.link_to 似乎是相同的东西。 - Tyler Collier
5
在Rails 3.2中出现了错误:undefined method 'helpers' for ActionController:Module - Nowaker
1
如果这个答案已经不再有效,它应该被删除,或者至少包括它所适用的Rails版本号。 - James
Rails 5.2 中出现错误:undefined method 'helpers' for ActionController:Module - alexandre-rousseau

0

我在使用ActionController.helper.my_method控制器中的内置助手方法时仍然遇到了问题。

显然,为每个flash使用render_to_string会起作用,但我不想为每个flash创建太多小的partials。

我的解决方案是为控制器创建一个小助手来执行partial中的代码。

控制器中的助手方法:

def h(&block)
  render_to_string(:partial => 'helper', :locals => {:block => block})
end

HAML 部分 (helper.html.haml):

= instance_eval &block 

在 ERB 中同样适用(helper.html.erb):

<%= instance_eval &block %>

在控制器中使用以下代码调用在帮助器中定义的 my_custom_helper_function 函数:

redirect_to url, :notice => h{my_custom_helper_function}

1
这是过度思考。 - alexandre-rousseau

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接