erb 数组迭代中 nil:NilClass 的未定义方法“each”

undefined method `each' for nil:NilClass on an erb array iteration

我目前在 Rails 5 应用程序中工作,您可以在其中搜索名字或姓氏,并且会显示该帐户的客户记录。但是我从搜索算法中得到了一个 Nil 对象 return。

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

如您所见,如果没有找到记录,假设 return 是一个空数组,但 return 是一个 Nil 对象。

customers/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]

首先你应该了解的是实例变量 return 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

我认为如果您只是将 @customer = 替换为 @customers = 就可以解决您的问题。

您可以使用#to_a 将 nil 转换为空数组

将其强制为 return 数组
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