Sometimes you have a maintenance script where you want to iterate over all ActiveRecord models. Rails provides this out of the box:
# script/maintenance_task.rb
# Load all models eagerly, otherwise you might only get a subset
Rails.application.eager_load!
ApplicationRecord.descendants.select(&:table_exists?).each do |model|
# ...
end
Caution
If you iterate over individual records, please provide a progress indicator: See https://makandracards.com/makandra/625369-upload-run-scripts-production
Caution
At makandra, we use our gem active_type Show archive.org snapshot for model inheritance. Depending on your use case, you might want to skip those models.
Full example
Rails.application.eager_load!
# Inlined here, but if you need this in multiple scripts, prefer the approach from the linked card above
module Enumerable
def with_progress(title = 'Progress')
total = count.to_f
each_with_index do |item, index|
progress = (index + 1) / total * 100
printf("#{title}: %.2f%%\r", progress)
yield item
end
puts "#{title} is done."
end
end
ApplicationRecord.descendants.select(&:table_exists?).each do |model|
# I wanted to iterate over all models with a CarrierWave uploader
attributes = model.uploaders.keys
next if attributes.empty?
# Skip active_type models
if model < ActiveType::RecordExtension::Inheritance
puts "Skipped ActiveType form model #{model}"
puts
next
end
# Perform your migration with helpful progress output
puts "Fixing uploads for #{model}: #{attributes.to_json}"
model.find_each.with_progress(model.to_s) do |record|
attributes.each do |attribute|
record.public_send(attribute).my_custom_migration_task!
end
end
puts
end
Posted by Klaus Weidinger to makandra dev (2025-12-01 09:34)