class Report
def quarterly_totals = …
def legacy_totals = …
end quarterly_totals is
reached through public_send every day, and legacy_totals by nothing at all.
The problem
The free dead_api greys out Report#legacy_totals in your editor: nothing in your recorded runs
called it. That’s a good question to ask, but it isn’t proof. Your suite doesn’t run the month-end
rake task, the admin export, or the webhook a partner hits twice a year. Any of them might call
legacy_totals, and grep won’t settle it:
class ReportsController < ApplicationController
def show
report = Report.new(params[:account_id])
render json: report.public_send("#{params[:kind]}_totals")
end
end
"#{params[:kind]}_totals" is only a method name at runtime. So the method stays. It gets tested,
documented and carried through every refactor, because nobody can prove it’s safe to delete.
The fix
Ask the hosted graph, which pools the runs from every deploy you’ve recorded:
$ ra prod_dead_api app/models/report.rb
pooled from 214 deploys · 91 days · 38.2M call trees
Report#legacy_totals
no production caller in 91 days safe to delete
Report#quarterly_totals
1 production caller: ReportsController#show via public_send
last called 3 days ago · 412 calls still alive
Report#csv_rows
only caller: its own spec no production caller in 91 days
quarterly_totals looked just as dead locally, and it’s reached through public_send from a real
controller. legacy_totals hasn’t been called by anything in three months of production traffic,
across every deploy. Delete it:
class Report
def quarterly_totals = totals_for(:quarter)
def csv_rows = rows.map(&:to_csv)
end
How it works
The recorder wraps every method your app defines, so a call is recorded however it was made:
directly, through send or public_send, from a callback or from a name built out of a string.
Each deploy you record ships its call trees to the hosted graph, where they pool into one.
prod_dead_api lists each public method with its production callers across that pool, and the last
time any of them called it. A method with none, over a window you choose, is flagged. Because each
call tree is stamped with its entry point, calls from your own specs are counted separately and never
keep a method alive.
That pooling is what turns the free tool’s question into an answer. dead_api knows what your laptop
ran. prod_dead_api knows what every server running your app did, for as long as you’ve recorded it.
Limits
- Only as long as your window. A method called once a year needs a year of recording to be seen. The report shows the window, so you can decide whether it’s long enough.
- Only the deploys you record. A worker fleet or a service you didn’t instrument can still call a method nothing else does.
- A report, not a deletion. It names the method and the evidence. Removing it is your call.
Related tools
dead_api
Find dead public API. Public methods no caller reached in any recorded run, including the ones whose only caller is their own spec. Greyed out in your editor.
See more →what_calls
Who can call this method. Every caller of a method from real runs, with where and how often. The calls that actually happened, not grep. what_it_calls does the reverse.
See more →coupling_map
Coupling from real load. Module and namespace coupling drawn from real production calls. Which parts of your app actually talk, and how much.
See more →