Module: TypedEAV::HasTypedEAV::DirtyTracking

Extended by:
ActiveSupport::Concern
Defined in:
lib/typed_eav/has_typed_eav/dirty_tracking.rb

Overview

Read-only, on-demand dirty tracking for typed Value rows that are part of a host association's in-memory target.

Pending comparisons follow Active Record's own dirty state; saved snapshots use the host lifecycle, not a separate Value mutation registry. A typed Value retains its database snapshot through attribute_in_database, while autosave clears its ordinary dirty state after a successful host save. Consequently failed saves and outer transaction rollbacks retain the same correction-friendly state that Active Record exposes on the child.

The association target is inspected without loading it. Named and nested assignment paths already place their touched Values in that target; callers using direct Value assignment should use a loaded typed_values association. A Value loaded independently from the host is intentionally outside this API because observing it would require an eager query of every Value row or a new global mutation registry.

Instance Method Summary collapse

Instance Method Details

#reloadObject

Reload replaces the host's association target. Clear the separate saved snapshot at the same boundary so it cannot outlive the state it describes.



119
120
121
# File 'lib/typed_eav/has_typed_eav/dirty_tracking.rb', line 119

def reload(...)
  super.tap { _typed_eav_clear_saved_changes }
end

#saveObject

Bracket the complete public save call, including callbacks that run after the model's create/update callbacks. An around_save callback cannot rescue an after_save callback that is compiled outside its around sequence, but these wrappers can restore the previous snapshot for both false returns and raised errors.



71
72
73
# File 'lib/typed_eav/has_typed_eav/dirty_tracking.rb', line 71

def save(...)
  _typed_eav_track_save { super }
end

#save!Object



75
76
77
# File 'lib/typed_eav/has_typed_eav/dirty_tracking.rb', line 75

def save!(...)
  _typed_eav_track_save { super }
end

#saved_typed_eav_changesObject

Logical changes from the most recent successful host save. The value is intentionally available in host after_save callbacks, where the child autosave has already consumed ordinary dirty state. This is successful-save state, not evidence that an outer transaction later committed and not a replacement for ValueVersion history.



62
63
64
# File 'lib/typed_eav/has_typed_eav/dirty_tracking.rb', line 62

def saved_typed_eav_changes
  (@typed_eav_saved_changes || {}).deep_dup
end

#typed_eav_changesObject

Pending typed-value changes keyed by effective Field name.

The returned hash and pairs are fresh objects. Before-values are reconstructed from the stored physical cells through the Field's public logical reader, so multi-cell fields retain the same shape as typed_eav_value rather than exposing storage-column details.



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/typed_eav/has_typed_eav/dirty_tracking.rb', line 41

def typed_eav_changes
  values = typed_eav_pending_values
  return {} if values.empty?

  names_by_field_id = typed_eav_effective_field_names
  changes_by_field_id = typed_eav_change_pairs(values, names_by_field_id)

  changes_by_field_id.each_with_object({}) do |(field_id, pair), changes|
    name = names_by_field_id[field_id]
    next unless name
    next if pair[0] == pair[1]

    changes[name] = pair.map(&:deep_dup)
  end
end