Module: ValidatesOverlap::RescueExclusionViolation

Defined in:
lib/validates_overlap/rescue_exclusion_violation.rb

Overview

Opt-in companion to the exclusion constraint (see MigrationHelpers): in the race window the validator cannot see, the constraint raises — this concern rescues that and turns it into a normal validation failure: save returns false with errors populated, save! raises ActiveRecord::RecordInvalid.

NOTE: a statement error aborts the innermost database transaction, so when the caller already has a joinable transaction open, save runs in its own savepoint (requires_new) with the rescue OUTSIDE it — otherwise the rescue would leave the caller's transaction in the aborted state. (The same pattern the Rails guides document for rescuing RecordNotUnique.) In every other situation the wrapper must NOT be added: ActiveRecord's own save transaction already contains the error there, and an extra wrapper at top level makes the save transaction JOIN it — silently swallowing the rollback a halted callback (throw :abort) relies on.

Example:

class Meeting < ActiveRecord::Base
validates :starts_at, :ends_at, overlap: { scope: :user_id }
include ValidatesOverlap::RescueExclusionViolation
end

Instance Method Summary collapse

Instance Method Details

#saveObject



23
24
25
26
27
28
29
# File 'lib/validates_overlap/rescue_exclusion_violation.rb', line 23

def save(...)
  contain_exclusion_violation { super }
rescue ActiveRecord::StatementInvalid => e
  raise unless ValidatesOverlap.exclusion_violation?(e)
  add_overlap_error
  false
end

#save!Object



31
32
33
34
35
36
37
# File 'lib/validates_overlap/rescue_exclusion_violation.rb', line 31

def save!(...)
  contain_exclusion_violation { super }
rescue ActiveRecord::StatementInvalid => e
  raise unless ValidatesOverlap.exclusion_violation?(e)
  add_overlap_error
  raise ActiveRecord::RecordInvalid, self
end