Module: Rollgeist

Defined in:
lib/rollgeist.rb,
lib/rollgeist/mark.rb,
lib/rollgeist/errors.rb,
lib/rollgeist/report.rb,
lib/rollgeist/railtie.rb,
lib/rollgeist/version.rb,
lib/rollgeist/notifier.rb,
lib/rollgeist/formatter.rb,
lib/rollgeist/configuration.rb,
lib/rollgeist/execution_state.rb,
lib/rollgeist/record_watchpoints.rb,
lib/rollgeist/patches/persistence.rb,
lib/rollgeist/patches/transactions.rb

Defined Under Namespace

Modules: ExecutionState, Notifier, Patches, RecordWatchpoints Classes: Configuration, ConfigurationError, Error, Formatter, GhostRecordAccess, Mark, Railtie, Report

Constant Summary collapse

MARK_IVAR =
:@__rollgeist_mark
REPORTED_IVAR =
:@__rollgeist_reported
SAVED_IVAR =
:@__rollgeist_saved
SUPPRESSION_KEY =
:__rollgeist_suppression_depth
VERSION =
"0.1.0"

Class Method Summary collapse

Class Method Details

.attach_mark!(record, attributes) ⇒ Object



98
99
100
101
102
103
104
105
106
# File 'lib/rollgeist.rb', line 98

def attach_mark!(record, attributes)
  mark = Mark.new(**attributes)
  RecordWatchpoints.install!(record)
  record.instance_variable_set(MARK_IVAR, mark)
  remove_ivar(record, REPORTED_IVAR)
  clear_transaction_write_state!(record)
rescue StandardError => error
  tracking_failure("mark attachment", error)
end

.capture_locationObject



127
128
129
130
131
132
# File 'lib/rollgeist.rb', line 127

def capture_location
  location = caller_locations(2, 50).find do |candidate|
    application_location?(candidate.path)
  end
  location && "#{location.path}:#{location.lineno}"
end

.clear_mark!(record) ⇒ Object



108
109
110
111
112
113
114
# File 'lib/rollgeist.rb', line 108

def clear_mark!(record)
  RecordWatchpoints.uninstall!(record)
  remove_ivar(record, MARK_IVAR)
  remove_ivar(record, REPORTED_IVAR)
rescue StandardError => error
  tracking_failure("mark cleanup", error)
end

.clear_record_state!(record) ⇒ Object



116
117
118
119
# File 'lib/rollgeist.rb', line 116

def clear_record_state!(record)
  clear_mark!(record)
  clear_transaction_write_state!(record)
end

.clear_transaction_write_state!(record) ⇒ Object



121
122
123
124
125
# File 'lib/rollgeist.rb', line 121

def clear_transaction_write_state!(record)
  remove_ivar(record, SAVED_IVAR)
rescue StandardError => error
  tracking_failure("transaction-state cleanup", error)
end

.configurationObject



28
29
30
# File 'lib/rollgeist.rb', line 28

def configuration
  @configuration ||= Configuration.new
end

.configure {|configuration| ... } ⇒ Object

Yields:



32
33
34
35
36
# File 'lib/rollgeist.rb', line 32

def configure
  yield(configuration)
  configuration.validate!
  configuration
end

.enabled?Boolean

Returns:

  • (Boolean)


49
50
51
# File 'lib/rollgeist.rb', line 49

def enabled?
  configuration.enabled_in?(environment)
end

.environmentObject



43
44
45
46
47
# File 'lib/rollgeist.rb', line 43

def environment
  return Rails.env.to_s if defined?(Rails) && Rails.respond_to?(:env)

  ENV.fetch("RAILS_ENV", ENV.fetch("RACK_ENV", "development"))
end

.install!(active_record_base) ⇒ Object



65
66
67
68
69
# File 'lib/rollgeist.rb', line 65

def install!(active_record_base)
  active_record_base.prepend(Patches::Transactions) unless active_record_base < Patches::Transactions
  active_record_base.prepend(Patches::Persistence) unless active_record_base < Patches::Persistence
  ExecutionState.install!
end

.mark_for(record) ⇒ Object



71
72
73
# File 'lib/rollgeist.rb', line 71

def mark_for(record)
  record.instance_variable_get(MARK_IVAR)
end

.mark_saved!(record) ⇒ Object



75
76
77
78
79
# File 'lib/rollgeist.rb', line 75

def mark_saved!(record)
  record.instance_variable_set(SAVED_IVAR, true) if enabled?
rescue StandardError => error
  tracking_failure("save tracking", error)
end

.reset!Object



38
39
40
41
# File 'lib/rollgeist.rb', line 38

def reset!
  @configuration = Configuration.new
  ExecutionState.reset!
end

.rollback_snapshot(record) ⇒ Object



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/rollgeist.rb', line 81

def rollback_snapshot(record)
  return unless enabled?

  action = rollback_action(record)
  return unless action

  {
    action: action,
    changed_attributes: rollback_changed_attributes(record, action),
    rolled_back_at: Time.now,
    rollback_location: capture_location
  }
rescue StandardError => error
  tracking_failure("rollback snapshot", error)
  nil
end

.suppressObject



53
54
55
56
57
58
59
# File 'lib/rollgeist.rb', line 53

def suppress
  previous_depth = ActiveSupport::IsolatedExecutionState[SUPPRESSION_KEY]
  ActiveSupport::IsolatedExecutionState[SUPPRESSION_KEY] = previous_depth.to_i + 1
  yield
ensure
  ActiveSupport::IsolatedExecutionState[SUPPRESSION_KEY] = previous_depth
end

.suppressed?Boolean

Returns:

  • (Boolean)


61
62
63
# File 'lib/rollgeist.rb', line 61

def suppressed?
  ActiveSupport::IsolatedExecutionState[SUPPRESSION_KEY].to_i.positive?
end

.tracking_failure(context, error) ⇒ Object



134
135
136
137
138
# File 'lib/rollgeist.rb', line 134

def tracking_failure(context, error)
  Kernel.warn("Rollgeist #{context} failure: #{error.class}: #{error.message}")
rescue StandardError
  nil
end