Reputation: 3345
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
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