Today I was debugging some RSpec tests that were failing intermittently. Eventually I narrowed the issue down to Devise’s
active_for_authentication? method, which was sometimes returning true and sometimes false.
I tried looking up the source code and had a WTF moment when I saw how
active_for_authentication? is defined in the
def active_for_authentication? true end
After a bit of research I learned via StackOverflow that you can use the
method method to find out where an object gets a method from. This showed me that my user model was actually using the
active_for_authentication? method defined in
user.method(:active_for_authentication?) #=> #<Method: User(Devise::Models::Confirmable)#active_for_authentication?>
This version of the function was a bit more complicated than merely returning
true. Sanity restored.
def active_for_authentication? super && (!confirmation_required? || confirmed? || confirmation_period_valid?) end
Eventually, I realized that the failing tests were caused by calling
Timecop.freeze in an unrelated test without calling
Timecop.return, which was messing with one of the time-based checks Devise does.
More about the
It returns an object of class
Method, which has a lot of other useful methods you can call:
user.method(:active_for_authentication?).source_location #=> ["/path/to/file.rb", 144] user.method(:active_for_authentication?).owner #=> Devise::Models::Confirmable user.method(:active_for_authentication?).parameters #=> 
You can also perform sorcery like assigning methods to variables and calling them, which I’m sure is useful sometimes although I can’t imagine such a scenario:
m = 12.method("+") m.call(3) #=> 15 m.call(20) #=> 32
The first thing they tell you when you start learning Ruby is “everything is an object”. I feel like I understand this better every day, even after two years of writing Ruby. Yes, everything is an object, including methods.