【问题标题】:undefined method error for instance variables in rails4 apprails4 app中实例变量的未定义方法错误
【发布时间】:2014-05-09 13:40:54
【问题描述】:

我正在练习书中的一个教程。在本教程中;需要在某些视图中显示来自几个模型的所有值。这些实例变量是在application_controller.rb 中的sidebar_values 方法下定义的:

helper_method :sidebar_values

def sidebar_values
    @food_prefs = FoodPreference.all
    @food_types = FoodType.all
    @cuisines = Cuisine.all
end

这里是application.html.erb的部分:

            <div class="col-lg-2">
                <div class="panel panel-primary" id="panels">
                    <div class="panel-heading">
                        Food Preferences
                    </div>
                    <% @food_prefs.each do |p| %> #42, error begins here
                        <p><%= p.name %></p>
                    <% end %>
                </div>
                <div class="panel panel-primary" id="panels">
                    <div class="panel-heading">
                        Food Types
                    </div>
                    <% @food_types.each do |t| %>
                        <p><%= t.name %></p>
                    <% end %>
                </div>
                <div class="panel panel-primary" id="panels">
                    <div class="panel-heading">
                        Cuisines
                    </div>
                    <% @cuisines.each do |c| %>
                        <p><%= c.name %></p>
                    <% end %>
                </div>
            </div> 

当我试图在视图中调用这些变量时,它会抛出如下错误:

NoMethodError - undefined method `each' for nil:NilClass:
    app/views/layouts/application.html.erb:42:in `_app_views_layouts_application_html_erb___4138475832854219665_70001190164060'

这些变量中的值不是nil,但是我无法从任何视图调用这些变量。

【问题讨论】:

  • 发表你的看法code
  • 您在哪一行收到该错误?
  • @Pavan 42 问题已更新
  • 你真的把这个方法称为sidebar_values吗?喜欢before_filter :sidebar_values 或在您的操作中?似乎您没有调用它,因此它没有设置实例变量——另外,我不明白为什么必须将其设为辅助方法,因为这些分配(以 @ 开头的实例变量)是通常在控制器中设置..
  • 在代码中很难找到第42行。能否请您突出显示错误行?

标签: ruby-on-rails ruby-on-rails-4 helper activemodel


【解决方案1】:

我知道您正在学习教程,但我认为缺少一些内容:

# application_controller.rb
before_filter :sidebar_values

def sidebar_values
  @food_prefs = FoodPreference.all
  @food_types = FoodType.all
  @cuisines = Cuisine.all
end

这个before_filter :sidebar_values 将对每个调用的操作调用sidebar_values 方法。您可以指定 only/except 选项来过滤一点受影响的操作:

before_filter :sidebar_values, except: [:login, :logout]

另外,我会为这个方法使用一个更好的名称,比如set_sidebar_variables,因为它正在为侧边栏设置实例变量。

正如我在 cmets 中解释的那样,我认为您不需要将其设为辅助方法,可以删除 IMO helper_method :sidebar_values


另一件事是您的 SQL 查询没有限制,您只需查询所有 3 个模型。从长远来看,这并不好。如果您有数百种美食、FoodTypes 和 FoodPrefs 怎么办?我会添加一个.limit(x) 以防止这种情况发生:

def sidebar_values
  @food_prefs = FoodPreference.limit(10)
  @food_types = FoodType.limit(10)
  @cuisines = Cuisine.all
end

【讨论】:

  • 它特别解决了这个问题,变量得到了,但我想知道我如何获得在辅助方法中定义的变量。
  • @ekremkrc 您可能必须在渲染侧边栏之前调用视图中的辅助方法,这将在您使用这些变量渲染视图之前设置您的变量。但是在视图中调用模型方法根本不是最佳实践......即使它们是通过帮助程序调用的——这就像在没有所有必需部件的情况下开始构建汽车,并且在构建过程中你要求这些缺失的部分。
【解决方案2】:

&lt;% @food_prefs.each do |p| %&gt; 上获得undefined method 'each' for nil:NilClass: 的原因是因为@food_prefs 变量为零。您正在调用一个方法:each 在一个 nil 变量上:@food_prefs。基本上,如果您打开rails console 并查询FoodPreference.count,它将返回zero 计数。要克服这个问题,请在数据库中创建此类的一个实例,以便您的计数不再为零。

或者:

用 if 语句环绕它。像这样:

<% if @food_prefs %>
  <% @food_prefs.each do |p| %> 
     <p><%= p.name %></p>
  <% end %>
<% end %>

当您确定您的 @food_prefs 不再是 nil 时,您可以稍后删除此 if statement

如何在辅助方法中定义变量:

虽然在这种情况下您可能不需要定义辅助方法,但您可以在 Helper 文件夹中的文件中定义它们。这是一个直截了当的红宝石。只需创建可以在视图中调用的方法。与控制器方法不同,您不需要 @ 符号。在您的 helpers 中创建的方法在您的视图中可用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-07-19
    • 1970-01-01
    • 2018-10-12
    • 2021-06-13
    • 1970-01-01
    • 2014-05-09
    • 2012-12-14
    • 2012-10-14
    相关资源
    最近更新 更多