dodgerogers747
dodgerogers747

Reputation: 3345

stub out :destroy for deleting public_activity record in request spec

I have a destroy method in my AnswersController which also destroys a public_activity record when its trackable object is deleted.

Answers Controller activity delete:

 def destroy
    @answer = Answer.find(params[:id])
    if @answer.destroy 
       @activity = PublicActivity::Activity.where(trackable_id: @answer.id, trackable_type: "Answer", owner_id: @answer.user.id).first
       @activity.destroy
       respond_to do |format|
          format.js
       end
    end
 end

My answers_spec.rb test fails with:

Answers deletes an answer
 Failure/Error: click_link "delete-answer"
 NoMethodError:
   undefined method 'destroy' for nil:NilClass
 # ./app/controllers/answers_controller.rb:41:in `destroy'
 # (eval):2:in 'click_link'
 # ./spec/requests/answers_spec.rb:20:in `block (3 levels) in <top (required)>'
 # ./spec/requests/answers_spec.rb:19:in `block (2 levels) in <top (required)>' 

I presume this is because the @activity instance variable you can see in the AnswersController hasn't been set and there is no public activity record to attempt to delete.

Is there a way to either create the @activity instance variable with the answers credentials so it can be deleted or a way to stub out the destroy method so the public_activity record isn't deleted?

answers_spec.rb

//omitted for brevity//

it "deletes an answer" do
    visit root_path
    sign_in_user
    create_and_find_question
    create_answer
    page.should have_selector("div", id: "delete-answer")
    expect {
      click_link "delete-answer"
    }.to change(Answer, :count).by(-1)
  end

answer_helper.rb

module AnswerHelper
  def create_and_find_question
    visit questions_path
    click_link "Ask a Question"
    page.should have_content "Step 1: Upload a Video"
    click_link "Step 2"
    page.should have_content "Step 2: Ask your question"
    fill_in "Title", with: "Ball starting too far left"
    fill_in "Body", with: "my clubface is closed..."
    expect {
      click_button "Save"
    }.to change(Question, :count).by(1) 
    page.should have_content "Question Created"
    page.should have_content "Add your answer"
  end

  def create_answer
    click_link "Add your answer"
    page.should have_selector("div", id: "new_answer")
    fill_in "answer_body", with: "You need to shift your weight better"
    expect {
      click_button "Save Answer"
    }.to change(Answer, :count).by(1) 
    page.should have_content "You need to shift your weight better"
  end
 end

Update

As per Peter's comment below, it would make sense to use rails inbuilt dependent destroy to handle deleting associated records. I have just tried to add this into the answers model:

has_many :activities, as: :trackable, dependent: :destroy

however it errors out with: NameError - uninitialized constant Answer::Activity:

The PublicActivity table is called activities. What name should I be using for this has_many association?

Upvotes: 0

Views: 782

Answers (1)

Peter Alfvin
Peter Alfvin

Reputation: 29399

While I think you should still try and figure out what is going wrong with your explicit delete, since it may indicate a problem elsewhere in your code, I'm going to respond here to your question about the use of has_many.

I think you're getting the NameError because the default name for the associated class (i.e. an unqualified Activity, derived from the word activities) is not correct. The associated class is PublicActivity::Activity. You can specify it with the class_name parameter, as described in http://guides.rubyonrails.org/association_basics.html#options-for-has-many. Note that you specify the associated class and let Rails deduce the associated table name; you do not specific the table name directly.

Upvotes: 1

Related Questions