Class: Whodunit::Chronicles::ChangeEvent
- Inherits:
-
Object
- Object
- Whodunit::Chronicles::ChangeEvent
- Defined in:
- lib/whodunit/chronicles/change_event.rb
Overview
Represents a database change event in a common format
This class normalizes database changes from different sources (PostgreSQL WAL, MariaDB binlog, etc.) into a consistent format for processing by audit systems.
Constant Summary collapse
- ACTIONS =
Supported database actions
%w[INSERT UPDATE DELETE].freeze
Instance Attribute Summary collapse
-
#action ⇒ Object
readonly
Returns the value of attribute action.
-
#metadata ⇒ Object
readonly
Returns the value of attribute metadata.
-
#new_data ⇒ Object
readonly
Returns the value of attribute new_data.
-
#old_data ⇒ Object
readonly
Returns the value of attribute old_data.
-
#primary_key ⇒ Object
readonly
Returns the value of attribute primary_key.
-
#schema_name ⇒ Object
readonly
Returns the value of attribute schema_name.
-
#sequence_number ⇒ Object
readonly
Returns the value of attribute sequence_number.
-
#table_name ⇒ Object
readonly
Returns the value of attribute table_name.
-
#timestamp ⇒ Object
readonly
Returns the value of attribute timestamp.
-
#transaction_id ⇒ Object
readonly
Returns the value of attribute transaction_id.
Instance Method Summary collapse
-
#==(other) ⇒ Boolean
Compare events for equality.
-
#all_data ⇒ Hash
Get all available data for this event.
-
#changed_columns ⇒ Array<String>
Get the changed columns for UPDATE events.
-
#changes ⇒ Hash
Get a hash of changes in [old_value, new_value] format.
-
#create? ⇒ Boolean
Check if this is a create event.
-
#current_data ⇒ Hash
Get the current data for this event.
-
#delete? ⇒ Boolean
Check if this is a delete event.
-
#initialize(table_name:, action:, primary_key:, old_data: nil, new_data: nil, timestamp: Time.now, schema_name: 'public', transaction_id: nil, sequence_number: nil, metadata: {}) ⇒ ChangeEvent
constructor
Initialize a new change event.
-
#inspect ⇒ String
Detailed string representation.
-
#qualified_table_name ⇒ String
Get the qualified table name (schema.table).
-
#to_h ⇒ Hash
Convert to hash representation.
-
#to_s ⇒ String
String representation.
-
#update? ⇒ Boolean
Check if this is an update event.
-
#validate_action(action) ⇒ Object
private
-
#validate_data_consistency ⇒ Object
private
Constructor Details
#initialize(table_name:, action:, primary_key:, old_data: nil, new_data: nil, timestamp: Time.now, schema_name: 'public', transaction_id: nil, sequence_number: nil, metadata: {}) ⇒ ChangeEvent
Initialize a new change event
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
# File 'lib/whodunit/chronicles/change_event.rb', line 29 def initialize( table_name:, action:, primary_key:, old_data: nil, new_data: nil, timestamp: Time.now, schema_name: 'public', transaction_id: nil, sequence_number: nil, metadata: {} ) @table_name = table_name.to_s @schema_name = schema_name.to_s @action = validate_action(action.to_s.upcase) @primary_key = primary_key || {} @old_data = old_data @new_data = new_data @timestamp = @transaction_id = transaction_id @sequence_number = sequence_number @metadata = || {} validate_data_consistency end |
Instance Attribute Details
#action ⇒ Object (readonly)
Returns the value of attribute action.
14 15 16 |
# File 'lib/whodunit/chronicles/change_event.rb', line 14 def action @action end |
#metadata ⇒ Object (readonly)
Returns the value of attribute metadata.
14 15 16 |
# File 'lib/whodunit/chronicles/change_event.rb', line 14 def @metadata end |
#new_data ⇒ Object (readonly)
Returns the value of attribute new_data.
14 15 16 |
# File 'lib/whodunit/chronicles/change_event.rb', line 14 def new_data @new_data end |
#old_data ⇒ Object (readonly)
Returns the value of attribute old_data.
14 15 16 |
# File 'lib/whodunit/chronicles/change_event.rb', line 14 def old_data @old_data end |
#primary_key ⇒ Object (readonly)
Returns the value of attribute primary_key.
14 15 16 |
# File 'lib/whodunit/chronicles/change_event.rb', line 14 def primary_key @primary_key end |
#schema_name ⇒ Object (readonly)
Returns the value of attribute schema_name.
14 15 16 |
# File 'lib/whodunit/chronicles/change_event.rb', line 14 def schema_name @schema_name end |
#sequence_number ⇒ Object (readonly)
Returns the value of attribute sequence_number.
14 15 16 |
# File 'lib/whodunit/chronicles/change_event.rb', line 14 def sequence_number @sequence_number end |
#table_name ⇒ Object (readonly)
Returns the value of attribute table_name.
14 15 16 |
# File 'lib/whodunit/chronicles/change_event.rb', line 14 def table_name @table_name end |
#timestamp ⇒ Object (readonly)
Returns the value of attribute timestamp.
14 15 16 |
# File 'lib/whodunit/chronicles/change_event.rb', line 14 def @timestamp end |
#transaction_id ⇒ Object (readonly)
Returns the value of attribute transaction_id.
14 15 16 |
# File 'lib/whodunit/chronicles/change_event.rb', line 14 def transaction_id @transaction_id end |
Instance Method Details
#==(other) ⇒ Boolean
Compare events for equality
163 164 165 166 167 168 169 170 171 172 173 174 175 |
# File 'lib/whodunit/chronicles/change_event.rb', line 163 def ==(other) return false unless other.is_a?(ChangeEvent) table_name == other.table_name && schema_name == other.schema_name && action == other.action && primary_key == other.primary_key && old_data == other.old_data && new_data == other.new_data && == other. && transaction_id == other.transaction_id && sequence_number == other.sequence_number end |
#all_data ⇒ Hash
Get all available data for this event
118 119 120 |
# File 'lib/whodunit/chronicles/change_event.rb', line 118 def all_data (old_data || {}).merge(new_data || {}) end |
#changed_columns ⇒ Array<String>
Get the changed columns for UPDATE events
86 87 88 89 90 |
# File 'lib/whodunit/chronicles/change_event.rb', line 86 def changed_columns return [] unless update? && old_data && new_data old_data.keys.reject { |key| old_data[key] == new_data[key] } end |
#changes ⇒ Hash
Get a hash of changes in [old_value, new_value] format
95 96 97 98 99 100 101 |
# File 'lib/whodunit/chronicles/change_event.rb', line 95 def changes return {} unless update? && old_data && new_data changed_columns.each_with_object({}) do |column, changes_hash| changes_hash[column] = [old_data[column], new_data[column]] end end |
#create? ⇒ Boolean
Check if this is a create event
65 66 67 |
# File 'lib/whodunit/chronicles/change_event.rb', line 65 def create? action == 'INSERT' end |
#current_data ⇒ Hash
Get the current data for this event
106 107 108 109 110 111 112 113 |
# File 'lib/whodunit/chronicles/change_event.rb', line 106 def current_data case action when 'INSERT', 'UPDATE' new_data when 'DELETE' old_data end end |
#delete? ⇒ Boolean
Check if this is a delete event
79 80 81 |
# File 'lib/whodunit/chronicles/change_event.rb', line 79 def delete? action == 'DELETE' end |
#inspect ⇒ String
Detailed string representation
155 156 157 |
# File 'lib/whodunit/chronicles/change_event.rb', line 155 def inspect "#<#{self.class.name} #{self}>" end |
#qualified_table_name ⇒ String
Get the qualified table name (schema.table)
58 59 60 |
# File 'lib/whodunit/chronicles/change_event.rb', line 58 def qualified_table_name "#{schema_name}.#{table_name}" end |
#to_h ⇒ Hash
Convert to hash representation
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
# File 'lib/whodunit/chronicles/change_event.rb', line 125 def to_h { table_name: table_name, schema_name: schema_name, qualified_table_name: qualified_table_name, action: action, primary_key: primary_key, old_data: old_data, new_data: new_data, current_data: current_data, changes: changes, changed_columns: changed_columns, timestamp: , transaction_id: transaction_id, sequence_number: sequence_number, metadata: , } end |
#to_s ⇒ String
String representation
147 148 149 150 |
# File 'lib/whodunit/chronicles/change_event.rb', line 147 def to_s pk_str = primary_key.map { |k, v| "#{k}=#{v}" }.join(', ') "#{action} #{qualified_table_name}(#{pk_str}) at #{}" end |
#update? ⇒ Boolean
Check if this is an update event
72 73 74 |
# File 'lib/whodunit/chronicles/change_event.rb', line 72 def update? action == 'UPDATE' end |
#validate_action(action) ⇒ Object (private)
179 180 181 182 183 184 185 |
# File 'lib/whodunit/chronicles/change_event.rb', line 179 def validate_action(action) unless ACTIONS.include?(action) raise ArgumentError, "Invalid action: #{action}. Must be one of: #{ACTIONS.join(', ')}" end action end |
#validate_data_consistency ⇒ Object (private)
187 188 189 190 191 192 193 194 195 196 197 198 |
# File 'lib/whodunit/chronicles/change_event.rb', line 187 def validate_data_consistency case action when 'INSERT' raise ArgumentError, 'INSERT events must have new_data' if new_data.nil? || new_data.empty? raise ArgumentError, 'INSERT events should not have old_data' unless old_data.nil? when 'UPDATE' raise ArgumentError, 'UPDATE events must have both old_data and new_data' if old_data.nil? || new_data.nil? when 'DELETE' raise ArgumentError, 'DELETE events must have old_data' if old_data.nil? || old_data.empty? raise ArgumentError, 'DELETE events should not have new_data' unless new_data.nil? end end |