2

I have a situation where I have a model in ruby that has been deleted in the database. The object still exists in memory. I want a way to check to see if the object in the db still exists.

If I debug the code, and stop on a breakpoint, I can see the object in the database through a sql query and through irb. However, in the debugger, I can evaluate expressions and have tried:

car.reload
Car.find(car.id)
Car.where(id: car.id)

All of which return a car that does not exist.

I am also trying to use ActiveModel::Dirty and tried this in the debugger:

car.changed?

This returns false.

TLDNR: All signs in the debugger point to it existing. The Db says it does not exist.

I have exhausted the option that the debugger is in a bad state. I am 1000% confident that the issue is with memory objects vs db objects.

How can I get the real state of the object from the code?

5
  • 1
    api docs for reload say that you'll get ActiveRecord::RecordNotFound if the record no longer exists. I've verified for myself that this is indeed the case (at least in ActiveRecord 4.0). So I'm not 1000% confident that the record really doesn't exist in your db. I guess we should start with which version of ActiveRecord are you using? Commented Sep 12, 2013 at 19:06
  • gem 'activerecord-import', '~> 0.3.1', gem 'activerecord-postgres-hstore', '~> 0.5.3', gem 'rails', "~> 3.2.13". And it is for sure not in the db Commented Sep 12, 2013 at 19:09
  • Behavior is the same in v3.2.13. So the answer to your question is to use #reload. Since that's not working for you, I can only suggest that you re-check your evidence that it's not in the db. Commented Sep 12, 2013 at 19:16
  • I can see how you would come to that conclusion, but I guarantee you that it is not in the db. Commented Sep 12, 2013 at 19:25
  • Not trying to say you're wrong, just that as stated the answer to your question is to use #reload or ::find. If that's not working, then something else is preventing the behavior you expect, not just that you don't know the right api. Commented Sep 12, 2013 at 19:27

2 Answers 2

2

Are you doing the destroy in a different thread? So when you do car.reload, did you previously do car.destroy in the same thread?

If the destroy is happening elsewhere, i.e. over a different database session, it's possible the transaction hasn't finished yet, so from the standpoint of the reloading thread, it's still in the database.

During the debug session, what if you try to select the record in a psql prompt? If you can reload the record, psql will almost certainly return the record. The exception is if you have some kind of ActiveRecord caching going on - then psql might not return the record, but you need to check.

To try to troubleshoot this further, right after the destroy happens, try logging or printing the number of open transactions using:

ActiveRecord::Base.connection.open_transactions

Another suggestion: Add logger statements before and after the destroy and also right before the breakpoint. Also set your logger level to debug so you can see the database statements. On postgres, look specifically for when the BEGIN, COMMIT, and ROLLBACK statements happen. Is the destroy actually committed before the breakpoint?

Sign up to request clarification or add additional context in comments.

2 Comments

Great advice. I will take a look at this. FYI - ActiveRecord::Base.connection.open_transactions returns 1 But the record is deleted in the app but is passed to a delayed job first! I bet this is the problem with the threads being in different states
@JonathanO It sounds like the current mystery is solved. As for how to fix the problem, I suggest opening a new question and linking to this one via comment.
1

You can do car.destroyed? to see if the object has been destroyed and is just hanging around in-memory only. Doc: http://apidock.com/rails/ActiveRecord/Persistence/destroyed%3F

5 Comments

that returns false but great idea.
Can you show the code you're using to do the delete from database? If deleted by a SQL query, or if deleted (instead of destroyed) then maybe that's why you'd get car.destroyed? # => false.
I am using a .destroy to get rid of the old one. But that is after the other is stored in memory. ie: c = Car.find(33) then d = Car.find(33) then d.destroy. Bet c still exists
Ahh, I get it now. I'm with @gregates, c.reload should raise ActiveRecord::RecordNotFound if the car is no longer in the database at that point. And c.reload would be the thing to do there to make sure. And, furthermore, Car.find_by_id(c.id) should return nil.
I wish that worked. I really need a way to force a check to the db

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.