Last active
February 9, 2026 13:54
-
-
Save jmhakvoort/d1556438177a213ddafeff542ca3b1a6 to your computer and use it in GitHub Desktop.
Cool Enumerable#each_with_progress I once wrote so I can see how long iterating will take. I have waited too long on empty processes already. Most of the code is a blatant copy of existing code I found on the interwebs, but unfortunately I don't remember where. My contributions are mostly with the RAILS_ENV guard and the output.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| module Enumerable | |
| def each_with_progress(&block) | |
| if ENV['RAILS_ENV'] == 'test' | |
| each do |element| | |
| block.call element | |
| end | |
| else | |
| out = $stderr | |
| time = Time.current | |
| total = count | |
| pretext = "> starting @ #{time.strftime('%H:%M')} -- processing #{total} items..." | |
| each_with_index do |element, i| | |
| out.print enumerating_line(i + 1, total, time) | |
| block.call element | |
| end | |
| end_time = Time.current | |
| duration = ((end_time - time) / 60).round(1) | |
| duration_unit = duration > 1 ? "minutes" : "seconds" | |
| out.print "\r< started @ #{time.strftime('%H:%M')} -- processed #{total} items in #{duration} #{duration_unit}\n" | |
| end | |
| self | |
| end | |
| protected | |
| def enumerating_progress_spinner | |
| @enumerating_progress_spinner ||= Enumerator.new do |e| | |
| loop do | |
| e.yield '|' | |
| e.yield '/' | |
| e.yield '-' | |
| e.yield '\\' | |
| end | |
| end | |
| end | |
| def enumerating_line(increment, total, time) | |
| percentage = (increment * 100.0) / total | |
| difference = (total * (Time.current - time)) / increment | |
| pretext = ["\r> started @ ", time.strftime("%H:%M"), " -- processing #{total} items ", '[ETA: ', (time + difference).strftime("%H:%M"), '] '].join | |
| posttext = format("[%5.1f%%]", percentage) | |
| progress = ((percentage / 100.0) * (Integer((`tput cols` || '80').chomp) - pretext.length - posttext.length - 2)).ceil.times.map {}.join('=') | |
| spinner = percentage >= 100 ? " " : enumerating_progress_spinner.next | |
| [pretext, progress, spinner, posttext].join(" ") | |
| end | |
| end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment