Checking if an ActiveRecord model instance was destroyed

ActiveRecord::Base#destroyed? was introduced in 2009, about a year before Rails 3.0 was released. Still, almost five years later, I regularly see code that tests a destroy action by querying the database after deleting the record to see if it still exists:

delete :destroy
Session.exist?(@session).should.be.false

# or:

lambda {
  delete :destroy
}.should.change('Session.count' -1)

# or even:

delete :destroy
lambda {
  @session.reload 
}.should.raise(ActiveRecord::RecordNotFound)

By using ActiveRecord::Base#destroyed?, you can ask ActiveRecord if #delete or #destroy was called on that specific object, without having to check the database:

describe SessionsController do
  before do
    @session = sessions(:harry)
    cookies[:authorization] = @session.token
  end

  it "logs the user out" do
    delete :destroy
    assigns(:session).should.be.destroyed
  end
end

Be sure to test this on the same instance you called #delete or #destroy on, though. Calling #destroyed? on @session instead of assigns(:session) in the above example would return false. That’s because #destroy and #delete actually set a @destroyed flag on the object, which is returned when you call #destroyed?.