Module: Familia::Horreum::DirtyTracking
- Included in:
- Familia::Horreum
- Defined in:
- lib/familia/horreum/dirty_tracking.rb
Overview
DirtyTracking - Tracks in-memory field changes since last save/refresh.
Provides a minimal ActiveModel::Dirty-inspired API for detecting which scalar fields have been modified. This is useful for:
- Knowing whether a save is needed
- Warning when collection writes happen with unsaved scalar changes
- Inspecting what changed and the old/new values
Fields are marked dirty automatically by the setter defined in FieldType. Dirty state is cleared after save, commit_fields, and refresh operations.
Instance Method Summary collapse
-
#changed_fields ⇒ Hash{Symbol => Array(Object, Object)}
Returns a hash of changed fields with [old_value, new_value] pairs.
-
#clear_dirty!(*field_names) ⇒ void
Clears dirty tracking state for all or specific fields.
-
#dirty?(field = nil) ⇒ Boolean
Whether any fields (or a specific field) have unsaved changes.
-
#dirty_fields ⇒ Array<Symbol>
Returns the set of field names that have been modified.
-
#mark_dirty!(field_name, old_value) ⇒ void
Mark a field as dirty, recording its old value before the change.
Instance Method Details
#changed_fields ⇒ Hash{Symbol => Array(Object, Object)}
Returns a hash of changed fields with [old_value, new_value] pairs.
The old value is captured at the time of the first change since the last clear. The new value is read from the current instance variable.
82 83 84 85 86 87 88 |
# File 'lib/familia/horreum/dirty_tracking.rb', line 82 def changed_fields @dirty_fields ||= {} @dirty_fields.each_with_object({}) do |(field_name, old_value), result| current_value = instance_variable_get(:"@#{field_name}") result[field_name] = [old_value, current_value] end end |
#clear_dirty!(*field_names) ⇒ void
This method returns an undefined value.
Clears dirty tracking state for all or specific fields.
Called automatically after save, commit_fields, and refresh. When field names are provided, only those fields are cleared, preserving dirty state for fields that were not persisted.
100 101 102 103 104 105 106 |
# File 'lib/familia/horreum/dirty_tracking.rb', line 100 def clear_dirty!(*field_names) if field_names.empty? @dirty_fields = {} else field_names.each { |f| @dirty_fields.delete(f.to_sym) } end end |
#dirty?(field = nil) ⇒ Boolean
Whether any fields (or a specific field) have unsaved changes.
56 57 58 59 60 61 62 63 64 |
# File 'lib/familia/horreum/dirty_tracking.rb', line 56 def dirty?(field = nil) @dirty_fields ||= {} if field @dirty_fields.key?(field.to_sym) else !@dirty_fields.empty? end end |
#dirty_fields ⇒ Array<Symbol>
Returns the set of field names that have been modified.
70 71 72 73 |
# File 'lib/familia/horreum/dirty_tracking.rb', line 70 def dirty_fields @dirty_fields ||= {} @dirty_fields.keys end |
#mark_dirty!(field_name, old_value) ⇒ void
This method returns an undefined value.
Mark a field as dirty, recording its old value before the change.
Called by the field setter in FieldType#define_setter. Only records the original value on the first change (subsequent changes update the current value but preserve the original baseline).
39 40 41 42 43 44 45 46 47 48 49 |
# File 'lib/familia/horreum/dirty_tracking.rb', line 39 def mark_dirty!(field_name, old_value) @dirty_fields ||= {} field_sym = field_name.to_sym # Only record the original old value on the first mutation. # Subsequent changes keep the original baseline so changed_fields # shows [original, current] rather than [previous, current]. unless @dirty_fields.key?(field_sym) @dirty_fields[field_sym] = old_value end end |