Debug with Metaprogramming in Ruby

Have you ever been unable to reproduce a bug in development?

Whenever you cannot reproduce a bug in development for various reasons, then you have to do it in staging (fingers crossed, not production).

Unfortunately, we have limited options in this environment.

One of them is to add logs in the code, commit, push, deploy, but depending on your setup, the feedback loop can be quite long.

Another option, is to use metaprogramming. Indeed, metaprogramming is also about reopening classes, or redefining methods for one instance.

The first step for you would be to open a rails console in your staging environment where the bug lives.

From this console you can start redefining methods to get the information you need.

Say we have a class like:

require 'csv'
class User <, :name)
  def to_csv
[name, email]
  def self.export(users)
  def self.create_csv(users)
CSV.generate do |csv|
csv << ["name", "email"]
users.each do |user|
csv << user.to_csv
  def self.post_to_api(string)
puts "sending to api"

I am going to simulate how you can redefine code definitions on the fly in the terminal.

Let us see a couple of examples of what could be done depending on the circumstances.

Exporting users tells us we actually send data to api but what if we need to check what data was sent?

Let us reopen the class and add the behaviour:

Now we can see what data is sent, but actually we do not want the api to be called in this case:

In a couple of class_eval we did change completely how the code works to get insights. You can do it for your own classes as for any gem. Of course this is not meant to persist and it should not beyond your Rails console.

I do not recommend this is production, but if you have any trouble, consider redeploying, it should wipe everything to original.

Oh, and you can of course use it for instance methods as well.

You can also patch one single instance:

Happy coding!

Thanks Tomasz Ras for proofreading!