集成测试时 nil:NilClass 的未定义方法“each”

undefined method `each' for nil:NilClass upon integration test

我正在 Rails 上使用 Ruby 开发一个网络应用程序,因为我对它还是很陌生,我忘记了我应该在我的应用程序代码之前编写测试和不想重做所以在我编写测试之前,我已经编写了我的应用程序代码并且它在浏览器上运行良好,但是在我编写集成测试之后,我有一大堆 ActionView::Template::Error: undefined methodeach' for nil:NilClass` 错误。

例如,我将复制并粘贴一个错误,我希望这些答案可以推断出我的其他类似错误。

错误:

ERROR["test_unsuccessful_edit", TransactionEditTest, 0.560911]
 test_unsuccessful_edit#TransactionEditTest (0.56s)
ActionView::Template::Error:         ActionView::Template::Error: undefined method `each' for nil:NilClass
            app/views/transactions/index.html.erb:4:in `_app_views_transactions_index_html_erb___2730839601929560472_70220029186400'
            app/controllers/transactions_controller.rb:32:in `update'
            test/integration/transaction_edit_test.rb:14:in `block in <class:TransactionEditTest>'
        app/views/transactions/index.html.erb:4:in `_app_views_transactions_index_html_erb___2730839601929560472_70220029186400'
        app/controllers/transactions_controller.rb:32:in `update'
        test/integration/transaction_edit_test.rb:14:in `block in <class:TransactionEditTest>'

  16/16: [=================================] 100% Time: 00:00:00, Time: 00:00:00

Finished in 0.59370s

对应的集成测试:

require 'test_helper'

class TransactionEditTest < ActionDispatch::IntegrationTest

  def setup
    @transaction = transactions(:test)
  end

  test "unsuccessful edit" do
    get edit_transaction_path(@transaction)
    assert_template 'transactions/edit'
    patch transaction_path(@transaction), transaction: { from:  "",
                                    to: "",
                                    amount:              "foo",
                                    description: "bar" }
    assert_template 'transactions/edit'
  end

这是我的控制器:

  class TransactionsController < ApplicationController
  def index
    @transactions = Transaction.all
  end

  def show
    @transaction = Transaction.find(params[:id])
  end

  def new                                               
    @transaction = Transaction.new
  end

  def create                                            
    if @transaction.save
      @transactions = Transaction.all
      render 'index'
    else
      render 'new'
    end
  end

  def edit                                            
    @transaction = Transaction.find(params[:id])
  end

  def update
    @transaction = Transaction.find(params[:id])
    if @transaction.update_attributes(transaction_params)
      redirect_to(:action => 'index')                                 
    else
      render('edit')
    end
  end 


  def destroy
    Transaction.find(params[:id]).destroy
    redirect_to transactions_path
  end

  private

    def transaction_params
      params.require(:transaction).permit(:from, :to, :amount,
                                   :description)
    end
end

和我的index.html.erb

<div class="transaction_list">


  <% @transactions.each do |transaction| %>

      <li>
        <%= transaction.from %>
        <%= transaction.to %>
        <%= number_with_precision(transaction.amount, :precision => 2) %>
        <%= transaction.description %>
        <%= link_to "Edit", edit_transaction_path(transaction.id) %> |
        <%= link_to "Delete", transaction, method: :delete, data: { confirm: "Are you sure?" } %>


      </li>
  <% end %>

</div>

我知道很多人已经在Whosebug上问过这个问题,但是我找不到和我有类似情况的人,我希望有人不仅指出我的错误,还给我解释一下概念,非常感谢!!

尝试

  def update
    @transaction = Transaction.find(params[:id])
    @transaction.update_attributes(transaction_params)
    redirect_to(:action => 'index')
  end 

  def update
    @transaction = Transaction.find(params[:id])
    if @transaction.update_attributes(transaction_params)
      redirect_to(:action => 'index')                                 
    else
      @transactions = Transaction.all
      render('index')
    end
  end

基本上,你需要在渲染前设置@transactions变量