Debugging a large codebase can sometimes be a pain, especially if you're new to it and you don't know about all the classes and relations in the system.
In this post I'd like to share a cool (IMO) way to debug not well-known codebase using dynamically created breakpoints. NB: yes, Ruby is so dynamic that you can create breakpoints on the go.
Assuming that you use byebug or pry, imagine that you've put a breaking point:
{% highlight ruby %} class PaymentValidator attr_accessor :credit_card
def initialize(checkout, attributes = {}) self.credit_card = checkout.create_credit_card binding.pry end end {% endhighlight %}
Inside the breaking point, you only know that there is a credit_card
object with errors
method
coming from ActiveModel::Errors.
You also expect that some other objects will be calling errors.add
, but you don't know who
and how will be doing it.
Here is what you can insert being in the breaking point:
{% highlight ruby %} mod = Module.new do def add(*args) binding.pry super end end credit_card.errors.extend(mod) {% endhighlight %}
This snipped will inject into add
method from credit_card.errors
and start debugging when someone
calls that method. Tricky, eh?
In my case, this dynamic breaking point helped me to find which objects have been adding errors on credit_card
object.
As an alternative, I could probably insert a breaking point into the ActiveModel::Errors#add
method,
but that would trigger too many breaking points that I'm not interested in, because ActiveModel::Errors#add
is used in other places of the same system.
Happy debugging!