NoMethodError当试图从Rails控制器调用辅助方法
当我尝试从我的一个控制器类访问我的一个辅助模块中定义的方法时,我得到一个NoMethodError
。 我的Rails应用程序使用helper
类方法,使用:all
符号,如下所示:
class ApplicationController < ActionController::Base helper :all . . end
我的理解是,这应该使我的所有控制器类自动包含在app / helpers目录中的所有帮助模块,因此混合到所有的方法到控制器。 它是否正确?
如果我明确地将控制器模块包含在控制器内,那么一切正常。
helper :all
帮助者(是的,所有这些)在视图中都可用,它不包含在控制器中。
如果你希望在助手和控制器之间共享一些代码,这是不太理想的,因为助手是UI代码,控制器就是控制器代码,你可以在控制器中包含助手,或者创build一个单独的模块,控制者和帮手。
要使用已经包含在模板引擎中的帮助器方法,
- Rails 2:使用
@template
variables。 - Rails 3:有很好的控制器方法
view_context
在控制器方法中调用“number_to_currency”的示例用法:
# rails 3 sample def controller_action @price = view_context.number_to_currency( 42.0 ) end # rails 2 sample def controller_action @price = @template.number_to_currency( 42.0 ) end
如果您需要在控制器和帮助程序/视图之间共享一个方法,您可以通过控制器顶部的“helper_method”来定义:
class ApplicationController < ActionController::Base helper_method :my_shared_method ... def my_shared_method #do stuff end end
希望有所帮助
控制器的辅助方法
得到你的帮手方法的一种方法是简单地包含你的帮手文件。
include LoginHelper cool_login_helper_method(x,y,z)
这会将该辅助模块的所有方法带入控制器的范围。 这并不总是一件好事。 为了保持作用域的独立性,创build一个对象,并使用该帮助对象的权力,并使用它来调用方法:
login_helper = Object.new.extend(LoginHelper) login_helper.cool_login_helper_method(x,y,z)
帮手:全部
helper :all
的助手模块都可以让你的所有视图 helper :all
可以使用所有的助手方法,但是它对你的控制器没有任何帮助。 这是因为辅助方法被devise用于视图,通常不应该从控制器访问。 在较新版本的Rails中,默认情况下,每个控制器都始终启用此选项。
对于Rails 3,在你的控制器中使用view_context
方法:
def foo view_context.helper_method ...
这是一个例子: http : //www.christopherirish.com/2011/10/13/no-view_context-in-rails-3-1-changes/
当我发现这是最需要的时间是写闪光灯,或自定义错误检查器。 很高兴在某些情况下使用flash_mail中的link_to helper等内容。 我使用以下解决scheme将ActionView帮助器添加到控制器中。 请注意,如上所述,这打破了MVC分离,所以如果有其他人有一个更好的主意,让我知道!
在ApplicationController下面添加这个:
class Something include Singleton include ActionView::Helpers::UrlHelper end
并在ApplicationController中添加
def foo Something.instance end
最后,在你要访问帮手代码的控制器中:
messages << "<li class='error'>Your have an Error!<%= foo.link_to('Fix This', some_path) %></li>"
希望有一些帮助!
使用助手方法可能更清洁:
class FooController < ActionController::Base def action self.class.helpers.helper_method arg end end
任何助手都可以在控制器中使用@templatevariables访问。
@ template.my_super_helper
控制器不能自动访问帮助器方法。 我们必须将其包含在应用程序控制器
模块ApplicationHelper
def hello_message "Hello World" end
结束
class ApplicationController <ActionController :: Base
include ApplicationHelper def message hello_message end
结束
助手将被用于模板,即。 意见,而不是在控制器。 这就是为什么你不能访问该方法。 如果你想在两个控制器之间共享一个方法,你就必须在ApplicationController中定义它。 helper:所有的说你在app / helpers目录中的任何助手文件中定义的任何方法都可以用于任何模板。
有两种方法可以做到这一点:创build一个模块或使用@templatevariables。 查看更多详情http://www.shanison.com/?p=305
如果您的应用app/helpers
文件夹中只有ApplicationHelper,则必须使用app/helpers
将其加载到您的控制器中。 默认情况下,Rails只加载与您的控制器同名的助手模块。 (例如ArticlesController将加载ArticlesHelper)。 如果你有很多模型(例如文章;post;类别),你必须上传每一个在你的控制器。 文档
帮手
module PostsHelper def find_category(number) return 'kayak-#{number}' end def find_other_sport(number) "basketball" #specifying 'return' is optional in ruby end end module ApplicationHelper def check_this_sentence 'hello world' end end
示例控制器
class ArticlesController < ApplicationController include ApplicationHelper include PostsHelper #...and so on... def show#rails 4.1.5 #here I'm using the helper from PostsHelper to use in a Breadcrumb for the view add_breadcrumb find_other_sport(@articles.type_activite), articles_path, :title => "Back to the Index" #add_breadcrumb is from a gem ... respond_with(@articles) end end
如果您将您的application_controller.rb文件更改为此…
class ApplicationController < ActionController::Base protect_from_forgery with: :exception include SessionsHelper end
那么所有的助手将可用于所有的控制器。