RecordNotFound raised when using find_by_id to get non-existent record in RSpec
Asked Answered
A

1

6

I've written this spec in products_controller_spec.rb, that is intended to test a redirect when destroy is called on a non-existent record:

it "deleting a non-existent product should redirect to the user's profile page with a flash error" do           
    delete :destroy, {:id => 9999}
    response.should redirect_to "/profile"
    flash[:error].should == I18n.t(:slideshow_was_not_deleted)
end

Here's the controller action in products_controller.rb:

def destroy
  product = Product.find_by_id(params[:id])
  redirect_to "profile" if !product
  if product.destroy
    flash[:notice] = t(:slideshow_was_deleted)
    if current_user.admin? and product.user != current_user
      redirect_to :products, :notice => t(:slideshow_was_deleted)
    else
      redirect_to "/profile"
    end
  else
    if current_user.admin?
      redirect_to :products, :error => t(:slideshow_was_not_deleted)
    else
      redirect_to "/profile"
    end
  end
end

Now, I didn't expect the spec to pass first time but I don't understand why it's failing with this:

Failure/Error: delete :destroy, {:id => 9999}
 ActiveRecord::RecordNotFound:
   Couldn't find Product with id=9999

I was under the impression that #find_by_id would not return RecordNotFound error on a non-existent record. So why am I getting one? Thanks in advance!

Alarm answered 17/4, 2012 at 9:55 Comment(4)
Which version of Rails do you use? This find_by_id works fine here with Rails 3.2.3. (returning nil instead of raising RecordNotFound)Fiery
3.2.2 here. I should add that find_by_id works in the browser. I'm only getting the RecordNotFound in the spec results.Alarm
- Actually, just tried in the browser with a show action on a non-existent record and got a RecordNotFound. Went away when I commented out the CanCan authentication in the controller. Looks like CanCan is throwing the RnFAlarm
I don't have enough rep to answer the question at the moment but in short, CanCan is throwing the error before the action runs. It can be patched, or more simply, the spec can be rewritten to expect the RnF. I'll post this as a formal answer later.Alarm
A
16

The RecordNotFound error was being thrown by CanCan. It's not rescue-able from within the controller action (presumably it occurs before the action runs). There were two ways of resolving it -

  1. Changing the spec to:

    it "deleting a non-existent product should result in a RecordNotFound Error" do         
      product_id = 9999
      expect { delete :destroy, {:id => product_id}}.to raise_error ActiveRecord::RecordNotFound
    end
    

or, 2. Patching CanCan like this.

I didn't fancy the patching route, so I went for option 1.

Alarm answered 17/4, 2012 at 21:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.