Last active
March 20, 2019 12:45
-
-
Save kerrizor/f9f9e86edfae5291902535b197f384a8 to your computer and use it in GitHub Desktop.
ActiveRecord Orphans
This file contains 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
desc "Check for ActiveRecord orphans" | |
task orphan_check: :environment do | |
# Silly housekeeping.. I'm sure there's a better way to spin up the app before | |
# we run the rake task but I A) can't remember and B) can't be bothered I'm | |
# just spiking some code here. Only PITA here is it makes us Rails specific. | |
# | |
Rails.application.eager_load! | |
ActiveRecord::Base.descendants.each{ |k| k.connection } | |
# Load up all the AR models in our app | |
# | |
ar_classes = ActiveRecord::Base.descendants | |
ar_classes.each do |klass| | |
# Find the klass's belongs_to relationships | |
# | |
belongs_to_assoc = klass.reflect_on_all_associations.select{|assoc| assoc.macro == :belongs_to} | |
if belongs_to_assoc.any? | |
puts "#{klass.name}" | |
puts "=" * klass.name.length | |
puts "\n" | |
belongs_to_assoc.each do |assoc| | |
# For the records that have a declared owner record, filter for ones | |
# where their owner's record's ID is nil, meaning that owner record | |
# does not exist in the DB. | |
# | |
results = klass.eager_load(assoc.name). | |
where("#{assoc.foreign_key} IS NOT NULL"). | |
where("#{assoc.plural_name}": { id: nil }) | |
if results.any? | |
puts "Missing #{assoc.class_name}" | |
puts "-" * (assoc.class_name.length + 8) | |
results.each do |result| | |
puts "#{klass.name} ID: #{result.id} \t #{assoc.class_name} ID: #{result.send(assoc.foreign_key)}" | |
end | |
end | |
end | |
puts "-"*80 | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I had to run it to feel like I understood it, but it worked for my test case and the sql makes sense.