【问题标题】:rails "undefined method" when invoking a helper method from layout view从布局视图调用辅助方法时出现“未定义的方法”
【发布时间】:2011-09-13 18:24:03
【问题描述】:

我有一个辅助方法可以在我的应用程序控制器中获取当前的购物车:

class ApplicationController < ActionController::Base
  protect_from_forgery

  helper :all # include all helpers, all the time

  private

  def current_cart
    if session[:cart_id]
      @current_cart ||= Cart.find(session[:cart_id])
      session[:cart_id] = nil if @current_cart.purchased_at
    end
    if session[:cart_id].nil?
      @current_cart = Cart.create!
      session[:cart_id] = @current_cart.id
    end
    @current_cart
  end

end

我可以从我的大多数视图中调用该方法,但我想在 views/layout/application.html.erb 文件中使用它, 像这样:

<div id="cart_menu">
    <ul>
    <li>
      <%= image_tag("cart.jpg")%>
    </li>
    <li>
      <%= link_to "#{current_cart.number_of_items}", current_cart_url %>
    </li>
    <li>
          <a href="/checkout/">Checkout</a>
        </li>
    </ul>
</div>

但是当我尝试这样做时,我得到了一个

undefined local variable or method `current_cart' for #<#<Class:0x2d2d834>:0x2d2b908>

错误..

有什么想法吗?

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3 layout


    【解决方案1】:

    您的示例失败,因为您在 ApplicationController 中定义了方法 current_cart,但视图中无法访问控制器方法。

    有两种方法可以实现你想要的:

    第一种方法是将方法current_cart 移动到帮助器中。

    第二种方法是使用before_filter 设置变量@current_cart 并在视图中使用@current_cart,见下文:

    class ApplicationController < ActionController::Base
      protect_from_forgery
    
      helper :all # include all helpers, all the time
    
      before_filter :set_current_cart
    
      private
    
      def set_current_cart
        if session[:cart_id]
          @current_cart ||= Cart.find(session[:cart_id])
          session[:cart_id] = nil if @current_cart.purchased_at
        end
        if session[:cart_id].nil?
          @current_cart = Cart.create!
          session[:cart_id] = @current_cart.id
        end
      end
    
    end
    

    在你看来:

    <%= link_to "#{@current_cart.number_of_items}", current_cart_url %>
    

    【讨论】:

    • @frank..我相信正确的答案是@Tumtu 所描述的:在您的应用程序控制器中添加helper_method :current_cart 以使视图可以访问此方法。这里描述的方法有一个缺点,你必须在特定的控制器中使用before_filter指定所有使用它的位置。否则过滤器将在每个操作之前执行。
    【解决方案2】:

    helper_method :current_cart 添加到您的应用程序控制器。

    class ApplicationController < ActionController::Base
      protect_from_forgery
      helper_method :current_cart
      ...
    end
    

    【讨论】:

    • 我已经使用了 helper: all - 这不应该包括所有方法作为助手吗?
    • @frank blizzard: helper :all 表示您将包含来自 app/helpers 的所有帮助程序的所有方法,并且这些方法将在视图中可用。但是helper_method 曾经将控制器方法声明为助手。
    • 好的,感谢您的澄清 - 将此更改为适当的答案,因为它仅在必要时执行,取消链接 before_filter 解决方案。
    【解决方案3】:

    辅助方法属于辅助模块,例如在app/helpers/application_helper.rb

    【讨论】:

    • 问题是如何在 application.html.erb 视图中访问我的 current_cart 对象?
    • 您可以将current_cart 方法原样放在帮助程序中。但就你而言,似乎你最好使用其他人提供的before_filter 方式。
    【解决方案4】:

    我实际上不确定,为什么这在其他视图中有效,但我认为,作为站点范围的逻辑,您应该将其定义为 ApplicationController 的 before_filter。如果您只需要在一个控制器中使用它,请将其放在那里。

    而且它不是“帮手”。 Helpers 存储在 app/helpers 中,通常用于通过在其方法中隐藏一些 html 来简化视图。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-08-22
      • 1970-01-01
      • 2011-01-24
      • 1970-01-01
      • 2011-11-19
      • 1970-01-01
      • 2013-06-11
      • 1970-01-01
      相关资源
      最近更新 更多