尝试从Rails控制器调用helper方法时出现NoMethodError

时间:2009-01-17 18:18:54

标签: ruby-on-rails ruby

当我尝试从我的一个控制器类访问我的一个辅助模块中定义的方法时,我得到NoMethodError。我的Rails应用程序使用helper类方法和:all符号,如下所示:

class ApplicationController < ActionController::Base
  helper :all
  .
  .
end

我的理解是,这应该使我的所有控制器类自动包含app / helpers目录中的所有辅助模块,因此将所有方法混合到控制器中。这是对的吗?

如果我在控制器中明确include辅助模块,那么一切正常。

14 个答案:

答案 0 :(得分:134)

使用模板引擎中已包含的辅助方法:

  • Rails 2:使用@template变量。
  • 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

答案 1 :(得分:49)

helper :all使视图中的所有助手(是的,所有助手)都可用,它不会将它们包含在控制器中。

如果你想在helper和controller之间共享一些代码,这不是很理想,因为helper是UI代码而控制器是控制器代码,你可以在控制器中包含帮助器,或者创建一个单独的模块和包括控制器和助手中的那些。

答案 2 :(得分:30)

如果你需要在控制器和助手/视图之间共享一个方法,你可以通过控制器顶部的'helper_method'进行定义:

class ApplicationController < ActionController::Base
  helper_method :my_shared_method
  ...

  def my_shared_method
    #do stuff
  end
end

希望有所帮助

答案 3 :(得分:28)

控制器的辅助方法

获取辅助方法的一种方法就是包含辅助文件。

include LoginHelper
cool_login_helper_method(x,y,z)

这会将该辅助模块中的所有方法带入控制器的范围。这并不总是一件好事。为了保持范围分离,创建一个对象,使用该帮助程序的权力灌输它,并使用它来调用方法:

login_helper = Object.new.extend(LoginHelper)
login_helper.cool_login_helper_method(x,y,z)

助手:全部

helper :all使您所有视图的所有帮助程序模块的所有辅助方法都可用,但它对您的控制器没有任何作用。这是因为辅助方法设计用于视图,通常不应从控制器访问。 在较新版本的Rails中,默认情况下,此选项始终为每个控制器启用。

答案 4 :(得分:7)

对于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/

答案 5 :(得分:5)

我觉得最需要的时候是写flash或自定义错误检查器。在某些情况下,很高兴在flash消息中使用link_to helpers之类的东西。我使用以下解决方案将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>"

希望以某种方式有所帮助!

答案 6 :(得分:5)

使用helpers方法可能更简洁:

class FooController < ActionController::Base
  def action
    self.class.helpers.helper_method arg
  end
end

答案 7 :(得分:4)

可以使用控制器中的@template变量访问任何帮助程序。

  

@ template.my_super_helper

答案 8 :(得分:3)

Controller无法自动访问辅助方法。我们必须将它们包含在app控制器中。

模块ApplicationHelper

 def hello_message
    "Hello World"
 end

class ApplicationController&lt;的ActionController ::基

  include ApplicationHelper

  def message
     hello_message
  end

答案 9 :(得分:2)

助手将与模板一起使用,即。视图,而不是控制器。这就是你无法访问该方法的原因。如果您想在两个控制器之间共享方法,则必须在ApplicationController中定义它。 helper:all表示你在app / helpers目录中的任何helper文件中定义的任何方法都可用于任何模板。

答案 10 :(得分:1)

有两种方法可以做到这一点:创建模块或使用@template变量。查看更多详细信息 http://www.shanison.com/?p=305

答案 11 :(得分:0)

如果您的app/helpers文件夹中只有ApplicationHelper,则必须使用include ApplicationHelper将其加载到控制器中。默认情况下,Rails仅加载与控制器同名的辅助模块。 (例如,ArticlesController将加载ArticlesHelper)。如果您有许多模型(例如文章;帖子;类别),那么您必须在控制器中上传每个模型。 the docs

辅助

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

答案 12 :(得分:0)

如果您将application_controller.rb文件更改为此...

{{1}}

...然后所有控制器都可以使用所有助手。

答案 13 :(得分:0)

请在ApplicationController中尝试include SessionsHelper

class ApplicationController < ActionController::Base
  include SessionsHelper
  ...
end