未定义的方法`each'for nil:NilClass在erb数组迭代中

问题描述:

我目前正在Rails 5应用程序中工作,您可以在其中搜索名字或姓氏,并显示该帐户的客户记录。不过,我正在从搜索算法返回一个Nil对象。未定义的方法`each'for nil:NilClass在erb数组迭代中

customers_controller:

class CustomersController < ApplicationController 
    def index 
    if params[:keywords].present? 
     @keywords = params[:keywords] 
     customer_search_term = CustomerSearchTerm.new(@keywords) 
     @customer = Customer.where(
     customer_search_term.where_clause, 
     customer_search_term.where_args). 
     order(customer_search_term.order) 
    else 
     @customers = [] 
    end 
    end 
end 

正如你可以看到,如果没有发现记录是假设返回一个空数组,但返回一个无对象。

客户/ index.html.erb

[![<header> 
    <h1 class="h2">Customer Search</h1> 
</header> 

<section class="search-form"> 
    <%= form_for :customers, method: :get do |f| %> 
    <div class="input-group input-group-lg"> 
     <%= label_tag :keywords, nil, class: "sr-only" %> 
     <%= text_field_tag :keywords, nil, 
          placeholder: "First Name, Last Name or Email Address", 
          class: "form-control input-lg" %> 

     <span class="input-group-btn"> 
     <%= submit_tag "Find Customers", class: "btn btn-primary btn-lg" %> 
     </span> 
    </div> 
    <% end %> 
</section> 

<section class="search-results"> 
    <header> 
    <h1 class="h3">Results</h1> 
    </header> 
    <table class="table table-striped"> 
    <thead> 
     <tr> 
     <th>First Name</th> 
     <th>Last Name</th> 
     <th>Email</th> 
     <th>Joined</th> 
     </tr> 
    </thead> 
    <tbody> 
     <% @customers.each do |customer| %> 
     <tr> 
      <td><%= customer.first_name %></td> 
      <td><%= customer.last_name %></td> 
      <td><%= customer.email %></td> 
      <td><%= l customer.created_at.to_date %></td> 
     </tr> 
     <% end %> 
    </tbody> 
    </table> 
</section>][1]][1] 

你应该了解的第一件事情是,如果他们没有被设置实例变量返回nil。如果你说@fake_var == nil这将是真实的,如果你在此之前从未定义@fake_var。您可以将其与常规局部变量进行对比,如果您尝试在定义之前使用它们,则会引发NoMethodError。例如,puts(fake_var)将引发fake_var的NoMethodError。

现在看看你的模板。不管它会循环通过@customers。如果尚未设置@customers,则会看到一个NoMethodError,因为您无法通过nil拨打each

最后,看看你的控制器动作:

def index 
    if params[:keywords].present? 
     @keywords = params[:keywords] 
     customer_search_term = CustomerSearchTerm.new(@keywords) 
     @customer = Customer.where(
     customer_search_term.where_clause, 
     customer_search_term.where_args). 
     order(customer_search_term.order) 
    else 
     @customers = [] 
    end 
    end 

具体的时params[:keywords].present?情况。在这种情况下,您从未设置@customers,因此当模板试图访问它时,它将为nil

我想如果你只是用替换它会解决你的问题。

您可以强制其使用#to_a它转换零到空数组阵列返回

def index 
    return [] unless params[:keywords] 
    @keywords = params[:keywords] 
    customer_search_term = CustomerSearchTerm.new(@keywords) 
    @customer = Customer.where(
    customer_search_term.where_clause, 
    customer_search_term.where_args). 
    order(customer_search_term.order 
).to_a 
end 

https://apidock.com/ruby/Array/to_a