.vbw-planning/milestones/07-rails-audit-and-refactoring/07-rails-audit-round-2/01-PLAN.md
Key context: LogCleanupJob uses batch.delete_all on FetchLog/ScrapeLog which skips dependent: :destroy callbacks, orphaning LogEntry records. Source has health_status default "working" in model but "healthy" in DB schema. Three log models duplicate identical sync_log_entry callbacks that belong in their shared Loggable concern. Item#soft_delete! decrements counter cache but has no restore! to re-increment. </context> <tasks> <task type="auto"> <name>Fix LogCleanupJob orphaned LogEntry records (H1)</name> <files> app/jobs/source_monitor/log_cleanup_job.rb test/jobs/source_monitor/log_cleanup_job_test.rb </files> <action> In LogCleanupJob, before each batch.delete_all call on FetchLog/ScrapeLog/HealthCheckLog, first delete the corresponding LogEntry records:
# Before deleting FetchLog batch:
SourceMonitor::LogEntry.where(loggable_type: "SourceMonitor::FetchLog", loggable_id: batch.select(:id)).delete_all
batch.delete_all
Apply this pattern to all three log type cleanup sections. Add tests that:
Note: Check what values the health module actually uses. The model says default "working", health module may use "healthy", "declining", "improving", "failing". Include all values that appear in the codebase. </action> <verify> PARALLEL_WORKERS=1 bin/rails test test/models/source_monitor/source_test.rb </verify> <done> Source has HEALTH_STATUS_VALUES constant, inclusion validation on health_status, migration aligns DB default to "working", scraping_enabled/scraping_disabled scopes added. </done> </task> <task type="auto"> <name>Add Item#restore! and fix counter cache symmetry (M3)</name> <files> app/models/source_monitor/item.rb test/models/source_monitor/item_test.rb </files> <action>
restore! method to Item that sets deleted_at to nil via update_columns and calls Source.increment_counter(:items_count, source_id). This is the symmetric counterpart to soft_delete!.