Why change-impact analysis is surprisingly hard in Ruby on Rails

ruby dev.to

Refactoring a mature Rails app often starts with a simple question:

If I change this method, what else could break?

In a smaller codebase, grep might be enough.

In a larger Rails app, not really.

A method can be connected through:

  • callbacks
  • associations
  • routes
  • background jobs
  • mailers
  • concerns
  • templates
  • tests
  • indirect Ruby callers

And because Ruby is dynamic, even resolving something that looks like a simple method call can become ambiguous.

That made change-impact analysis an interesting problem to work on.

The rule I chose early

I'd rather miss an ambiguous relationship than confidently invent one.

So instead of pretending every relationship is certain, the analyzer records evidence and confidence around what it finds.

For example:

ripple-effect inspect 'BillingService#charge'
Enter fullscreen mode Exit fullscreen mode

The goal is to answer questions like:

  • Who calls this?
  • Which Rails components depend on it?
  • What can reach it indirectly?
  • Which tests are likely relevant?
  • Why does the analyzer think this relationship exists?
  • Where is it unsure?

You can also inspect the impact of a branch:

ripple-effect diff main
Enter fullscreen mode Exit fullscreen mode

The result became RippleEffect

RippleEffect is an open-source Ruby gem for static change-impact analysis in Rails apps.

It does not:

  • boot the Rails app
  • connect to the database
  • evaluate application code
  • upload source
  • call an LLM

Everything is analyzed locally and deterministically.

I've been testing the first release against real Rails codebases including Lobsters, RubyGems.org, Solidus, and Mastodon.

There are still plenty of hard cases in dynamic Ruby, which is exactly what makes the problem interesting.

If you work on large Rails apps, I'd be curious:

How do you currently answer "what else could this change affect?" before a refactor?

GitHub: https://github.com/iamzayn19/ripple-effect

RubyGems: https://rubygems.org/gems/ripple_effect

Source: dev.to

arrow_back Back to Tutorials