Mastodon

Finding methods in a Ruby codebase with Pry

Pry has been becoming a bigger and bigger part of my Ruby development workflow lately. Test not working? Pry. Debugging production from the console? Pry. Rake task doing something incomprehensible? Pry. But for finding stuff within a codebase my goto solution is still grep:

grep -ri def\ my_method .

Recently I grepped for a method called param_search_query in a project I am working on and came up with nothing.
After some head scratching and digging through some gems I thought I would try ctags.
Nothing. So I decided to see if Pry could help.

    30:   def has_query?
 => 31:     binding.pry
    32:     self.param_search_query && self.param_search_query.present? && self.param_search_query != "Eventname"
    33:   end
    34: 
    35:   def tickets
    36:     @tickets = Ticket.with_min_price
pry(#<Search:0x7fa5ea6f59e0>)> show-method self.param_search_query

It pry’s show-method function revealed the source of the confusion (pardon the pun), the method was being dynamically generated:

From: /home/mike/projects/frontend-server/app/models/search.rb @ line 20:
Number of lines: 7

define_method "param_#{psp}" do
  if self.search_params && self.search_params[psp].present?
    self.search_params[psp]
  elsif self.project
    self.project.get_param(psp)
  end
end

How did I get any work done without this?

Ruby redo’s: IRB

I have come to the realization that the best thing you can do to advance your Rails knowledge is to get better at Ruby. Rails development tends to keep you in one particular corner of the language. To see the other parts you really need to step off Rails’ golden path and try writing something from scratch yourself.

To push myself into some interesting territory I have taken to creating toy implementations of some of the programs I use but have never really understood the internals of. Every time I do this I find I learn something new… sometimes something big, sometimes something small.

One of the small ones actually started with switching from IRB to Pry, and seeing the mind blowing simplicity of Josh Cheek’s example Read Evaluate Print Loop (REPL):

loop do
  puts eval gets
end

When he showed that I nearly fell out of my chair. I’ve been using the Rails console for years now and had never really stopped to consider how it actually did what it does. Obviously IRB is a bit more more involved than a one-liner and a gemspec but this is one of those magic code examples that gets the concept across with searing clarity.

A learning opportunity is not far off either since its not long before you will get the urge to improve it after fat-fingering something and the having it exit. If you don’t know about Ruby’s Exception hierarchy, or like me needed a reminder because you have spent to much time with Rails, try adding some error handling catching the Exception class:

loop do
  begin
    puts eval gets
  rescue Exception => e #Not a good idea!
    puts e.message
  end
end

Of course you will soon realize that you can’t end the program since it turns out that Kernel#abort just calls Kernel#exit and that actually exits the program by raising a SystemExit Error… which we just caught. Oops.
After discovering the joy of Kernel#exit! and doing some reading about the Exception hierarchy (Ahhaa StandardError!) I have to say that redoing even seven lines of IRB taught me a lot.