seancdavis
seancdavis

Reputation: 2821

Object is nil after calling a method in Rails test environment

I'm experiencing unexpected behavior in running tests with rspec and rails. I have a class method, create_and_save, which saves an association to a recipient object.

If, at any point in this method, I output the recipient, I get what I expect:

Rails.logger.debug recipient.to_s
# => #<User:0x007fb712572210>

But as soon as I try to access an attribute or method on the recipient, I run into an error.

Rails.logger.debug recipient.id.to_s
# => undefined method `id' for nil:NilClass

Rails.logger.debug recipient.valid?.to_s
# => undefined method `valid?' for nil:NilClass

If I check for nil? the behavior follows a similar pattern. Without another call, I'm fine:

Rails.logger.debug recipient.nil?.to_s
# => false

But when I try to access a method, recipient is retroactively nil.

Rails.logger.debug recipient.nil?.to_s
# => true
Rails.logger.debug recipient.id.to_s
# => undefined method `id' for nil:NilClass

In development, the method works as expected. So I'm guessing this has something to do with how my test environment is running, but I'm not sure where to look.

Upvotes: 2

Views: 277

Answers (2)

seancdavis
seancdavis

Reputation: 2821

In working to add more context to my problem, I found the culprit. The method was being called twice. The first time the recipient was indeed nil, while when it ran the second time, it had a recipient.

Validations and better checks for nil objects would have likely caught this sooner.

I will also note that the reason I believed Rails.logger.debug recipient.nil?.to_s was returning false when I didn't attempt to access an attribute was because that's what I saw at the end of the transaction. Because the initial call occurred in the middle of several transactions, it got lost in the mess. Using puts to print to the window running rspec made this easier to debug.

Upvotes: 0

KARASZI Istv&#225;n
KARASZI Istv&#225;n

Reputation: 31477

Make sure that your database is up-to-date in you test environment.

The easiest way is to recreate the test DB with:

RAILS_ENV=test rake db:drop db:create db:migrate

Upvotes: 1

Related Questions