Передача параметров формы в rspec - PullRequest
1 голос
/ 05 января 2012

Я использую act_as_audited. В контроллере действия уничтожения я передаю значение комментария аудита. Все это работает хорошо, но когда я пытаюсь проверить действие уничтожения, я получаю:

PurchasesController DELETE /destroy deletes the correct Purchase
 Failure/Error: delete :destroy, id: i
 NoMethodError:
  You have a nil object when you didn't expect it!  
  You might have expected an instance of Array.  
  The error occured while evaluating nil.[] 
# ./app/controllers/purchases_controller.rb:79:in `destroy'
# ./spec/controllers/purchases_controller_spec.rb:156:in `block (3 levels) in <top (required)>'

Строка № 79 гласит: @purchase.audit_comment = params[:purchase][:audit_comment]

Вот мой код:

PurchasesController

def destroy
  @purchase = Purchase.find(params[:id])
  @purchase.audit_comment = params[:purchase][:audit_comment]
  respond_to do |format|
    if @purchase.destroy
      format.html { redirect_to(purchases_url, notice: "Successfully destroyed purchase.") }
      format.xml  { render :xml => @purchase, :status => :deleted, :location => @purchase }
    else
      flash[:alert] = "#{@purchase.po_number} could not be destroyed"
      render 'show'
    end
  end
end

Покупки show.html.erb РЕДАКТИРОВАНИЕ

<%= form_for @purchase, method: :delete do |builder| %>

<% if @purchase.errors.any? %>
  <div id="error_explanation">
    <h2><%= pluralize(@purchase.errors.count, "error") %> prohibited this purchase from being saved:</h2>

    <ul>
    <% @purchase.errors.full_messages.each do |msg| %>
      <li><%= msg %></li>
    <% end %>
    </ul>
  </div>
<% end %>

<% title "Purchase" %>

<div id="delete_button">    
  <span><strong>PO Number:  <%= @purchase.po_number %></strong></span>
    <%= render "audit_comment", f: builder %>
    <%= builder.submit "Destroy Purchase"%>
</div>  
<% end %>
<p>
  <%= link_to "Edit", edit_purchase_path(@purchase) %> |
  <%= link_to "View All", purchases_path %>
</p>

_audit_comment.html.erb - Закупки

<div id = "audit">
  <%= f.label :audit_comment %>:<br />
  <%= f.text_area :audit_comment, :size => "60x5" %>
</div>

purchase_controller_spec.rb

require 'spec_helper'
require 'ruby-debug'

describe PurchasesController do
  login_user
  render_views

  before(:each) do
    @purchase = Factory(:purchase)
  end

  describe "DELETE /destroy" do
    before(:each) do
      @ability.can :destroy, Purchase      
    end  
    it "deletes the correct Purchase" do
      i = @purchase.id
      c = Purchase.count
      pl = Purchase.find(i).purchase_line_items
      cpl = pl.count
      delete :destroy, id: i
      Purchase.count.should == c-1
      pl.count.should == cpl-1
      response.should redirect_to(purchases_path)
      flash[:notice].should == "Successfully destroyed purchase."
    end
    it "redirects to the index page with an alert when a delete fails" do
      i = @purchase.id
      c = Purchase.count
      pl = Purchase.find(i).purchase_line_items
      cpl = pl.count
      Purchase.any_instance.stubs(:valid?).returns(:false)
      delete :destroy, id: i
      Purchase.count.should_not == c-1
      pl.count.should_not == cpl-1
      response.should render_template('show')
      flash[:alert].should == "#{@purchase.po_number} could not be destroyed"
    end
  end
end

Любая помощь приветствуется. Спасибо!

1 Ответ

2 голосов
/ 06 января 2012

Это говорит о том, что в строке 79 params[:purchase] равно нулю.

Причина, по которой он равен нулю, заключается в том, что button_to генерирует собственный тег формы. Таким образом, теперь у вас есть <form> в пределах <form>, и ваше поле для комментариев аудита не отправляется. Вместо button_to вы должны использовать builder.submit. Вам также нужно будет установить опцию :method в вашем вызове на form_for, чтобы сделать запрос DELETE.

Обновление после редактирования вопроса

HTML теперь выглядит нормально, но я вижу проблему со спецификацией. Я думаю, что вы забыли передать комментарий аудита своим HTTP-параметрам. Он есть в HTML, но ваша спецификация обходит форму, потому что тестирует контроллер изолированно. (Интеграционный тест будет использовать фактическую форму. Контроллерные тесты этого не делают.) Поэтому вам придется вручную добавлять в запрос любые параметры формы, которые ожидает контроллер. Например:

delete :destroy, :id => 1, :purchase => {:audit_comment => 'Test comment'}
...