The Lightning Talk

I currently work at a company called SimpleNexus. During a recent development leadership training, I gave a lightning talk on random things that I wish I knew were possible in Ruby when I originally started working with it almost four years ago. I have listed six of those random things here below. I use these things often as I am debugging Ruby code in my daily work.

_ returns last evaluated expression

The Rails Console is one of the best features of Ruby. I use it almost every day to debug things locally or in our test and integration environments. One thing that makes working in the console easier, is the fact that you can use _ to reference the result of the previous statement. This changed my life! I frequently forget to save something to a variable, and I used to have to go back to the previous command and edit it to save its result. It isn't extremely hard to do that but using _ does save some time, especially when the previous statement is an unoptimized ActiveRecord query.

  "Hello World"
  var = _ + '!'
  var # => "Hello World!"

.method().source

The next tip is a method called method. It returns a method object and then you can call source to (yep, you guessed it) return the source code of that method in the Rails Console. This is particularly useful when your codebase includes some meta programming and there are dynamically defined methods on the object that you are debugging. This means that you could search your codebase for that method and potentially never find where it was defined. Printing out the source code will allow you to find out not only what the method does but gives you more to search for so you can find it in your project. It is also useful for different gems that have incomplete documentation. Sometimes you have to dig through the full source code anyways but often you can just look at the single method in the console and get what you need.

  # View source code of a method in rails console
  # Nice for finding the code responsible for dynamically defined methods
  m = Model.last
  m.method_dynamically_created # using the method called define_method 
  puts m.method(:method_dynamically_created).source
  
  # Also can be used to lookup gem functions
  puts BCrypt::Password.method(:create).source # what options?
  BCrypt::Password.create(password, {cost: 14})

- Object.methods

Not only is it nice to be able to see the source code of a method, but to see what methods you can call on an object. Ruby's Object class has a method called methods that returns an array of symbols of method names that you can call on that object. The annoying thing is the array contains all the default methods up the inheritance chain to the Object class itself. The cool thing is we can subtract Object.methods from that array to be left with methods that are unique to our object only. This same thing can be done with public and private methods and combined with any other Ruby method to quickly search and sort through methods to find what you are looking for right from the Rails Console.

  # In ruby [] - [] does a set difference (I also love array set operations)
  # this is usefully when debugging and you want to know what methods are available
  
  object = []
  [].methods
  [].methods - Object.methods
  [].public_methods
  [].public_methods - Object.public_methods
  [].private_methods
  [].private_methods - Object.private_methods
  
  # You can also use any other ruby methods for searching through the list
  ([].public_methods - Object.public_methods).select{ |m| m.to_s =~ /^to_/ }

.class_eval

Another useful thing is a method called class_eval. It isn't something you should ever use in code that is deployed to a production environment but is very useful for debugging things in an integration environment. There are somethings sometimes that you can't reproduce locally! class_eval lets you dynamically edit a class. This means you can redefine methods and add log statements, or disable different actions that you don't want to fire while debugging. It lets you test out a fix quickly without having to submit your code through review before pushing it to the integration environment. class_eval will change the method for all instances of that class in your process. If you want to edit a single instance's method only, you can use the syntax shown below.

  m = Model.last
  m.method_to_debug # Doesn't have log statements at first
  Model.class_eval do
    def method_to_debug 
      puts "Hello I'm a debug statement here in the method"
      # ... Rest of the code that you want the method to call
    end
  end
  s.method_to_debug

  # Overwrites the object's singleton class to only change the method for this object
  m2 = Model.first
  def m2.method_to_debug
    puts "Hello I'm a different debug statement from only this object"
    # ... 
  end
  s2.method_to_debug # => "Hello I'm a different debug statement from only this object"
  s.method_to_debug # => "Hello I'm a debug statement here in the method"

.send method

The send method in Ruby is used to call methods dynamically on an object. This is one of those Ruby features that shouldn't be regularly used in production, although there are plenty of valid use cases. Any time that send is used, I think that it reduces the readability of the code and makes it harder to search through a project, which makes maintenance and refactoring all the more difficult. My favorite part of send is that it allows you to call private methods on an object. This is nice when you are debugging in the console, and are trying to figure out what a private method returns. If you call the private method directly you will get an error, but using send gets around that so you can see what is going on and fix the problem.

  # Debugging a private method
  m = Model.last
  m.private_method # => Error
  m.send(:private_method) # => Executes code

Indexing into a String with Regex

This is my favorite feature in all of Ruby. I used to work at a web scraping company. While working there I used to dream (have nightmares?) about Regex because of how much we had to use it to get people the data they were looking for. Regex is the black magic of programming and Ruby makes them super easy to use. The syntax shown in the code block below highlights how easy it is to extract a substring using a Regex in Ruby. Once again, I wouldn't use this in production code very often because the data should be formatted better, but for things like Advent of Code, or random scripts easier to write.

  # This is one of my favorite ruby features
  string = "Test: this is a blog post"
  string[/Test: (.*)/, 1] # => "this is a blog post"

Ruby is Life

When I first started using Ruby, I didn't think I would like it. The more I have used it, the more I have come to love it. It's simple, elegant, and has a lot of powerful features. The six I have mentioned here aren't the most impressive features Ruby has to offer, but six random tips that might help you improve your debugging.