One problem that crops up as a Ruby on Rails application evolves is that new attributes are added to existing models, sometimes with new validation rules. For example, you may have a Customer model with name, address, email and phone number, then realize you want to add an attribute to store email marketing preferences many months later. If you add a validation to the new attribute, any new records will be appropriately validated, but the old records won’t have any value. In some cases you may be able to provide a default value in the database migration but this might not always be desirable or possible. These old model records that no longer pass validation can cause serious problems in an application, especially if you validate records through model associations and you have validation errors that aren’t expected.
To work around this, I created a quick little rake task that will find all your model classes, find all the model records and run validation on each record. In instances where the validation fails it will output the model name and the ID of the record that failed validation.
namespace :validate do
desc "Validates all model records"
task :models => :environment do
Dir.glob(Rails.root.to_s + '/app/models/*.rb').each { |file| require file }
objects = ObjectSpace.each_object(Class) do |klass|
if ActiveRecord::Base > klass
begin
all_records = klass.all
rescue
puts "Error querying model #{klass} - maybe the table doesn't exist?"
next
end
all_records.each do |r|
if !r.valid?
puts "Invalid record in model #{klass} with id #{r.id}!"
end
end
end
end
end
end
Also available here on Gist.