2012-01-05 3 views
1

J'utilise acts_as_audited. Dans le contrôleur de l'action destroy, je transmets la valeur du commentaire d'audit. Tout cela fonctionne bien, mais lorsque je tente de tester la détruire l'action que je reçois:Passing form params dans rspec

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)>' 

Ligne # 79 est ainsi libellé: @purchase.audit_comment = params[:purchase][:audit_comment]

Heres mon code:

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 

Achats show.html.erb EDITED

<%= 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 - Achats

<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 

Toute aide est appréciée. Merci!

Répondre

2

Il vous dit qu'à la ligne 79, params[:purchase] est nul.

La raison pour laquelle il est nul est que button_to génère son propre tag de formulaire. Ainsi, vous avez maintenant un <form> dans un <form>, et votre champ de commentaire d'audit n'est pas soumis. Au lieu de button_to, vous devez utiliser builder.submit. Vous devrez également définir l'option :method dans votre appel au form_for pour en faire une demande DELETE.

mise à jour après modification à la question

Le HTML semble maintenant OK, mais je vois un problème avec la spécification. Je pense que vous oubliez de transmettre le commentaire d'audit à vos paramètres HTTP. Il est présent dans le code HTML, mais votre spécification contourne le formulaire, car il teste le contrôleur de manière isolée. (Un test d'intégration utiliserait le formulaire actuel, ce qui n'est pas le cas pour les tests de contrôleur.) Par conséquent, vous devrez ajouter manuellement à la requête tous les paramètres de formulaire attendus par le contrôleur. Par exemple:

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

J'ai modifié le formulaire et je peux toujours supprimer des achats tant qu'un commentaire d'audit se trouve dans la zone de texte. La seule chose est que le test échoue toujours avec la même erreur. Merci pour votre réponse. – brink

+0

Pouvez-vous éditer votre question avec le nouveau HTML? Je vois qu'il a encore button_to dedans. Peut-être que je peux déterminer quelle est l'erreur si je peux regarder ce que vous avez maintenant. – rlkw1024

+0

La page d'affichage a le nouveau HTML. – brink

Questions connexes