Class: WhittakerTech::Aeon::Allocation

Inherits:
ApplicationRecord show all
Defined in:
app/models/whittaker_tech/aeon/allocation.rb

Overview

An immutable temporal law attached to a host record via polymorphic +schedulable+. Allocations are never edited in place — future changes are expressed through Forker, which closes the current allocation and creates a successor linked via +supersedes_allocation_id+.

Temporal fields are protected by a +before_update+ guard that raises ActiveRecord::ReadonlyAttributeError. Services bypass this via +update_column+/+update_columns+ which skip callbacks by design.

See Also:

Constant Summary collapse

TEMPORAL_FIELDS =

Fields that are immutable once the allocation is persisted. Any AR-level mutation of these triggers +ReadonlyAttributeError+.

%w[
  temporal_kind starts_at duration_seconds timezone rrule
  valid_from valid_to projected_until
  supersedes_allocation_id schedulable_type schedulable_id schedulable_label
].freeze

Instance Attribute Summary collapse

Instance Attribute Details

#invalidated_occurrencesActiveRecord::Associations::CollectionProxy<Occurrence> (readonly)

Occurrences from a predecessor allocation that were invalidated when this allocation was created via a fork.

Returns:

  • (ActiveRecord::Associations::CollectionProxy<Occurrence>)


77
78
79
80
# File 'app/models/whittaker_tech/aeon/allocation.rb', line 77

has_many :invalidated_occurrences,
class_name: 'WhittakerTech::Aeon::Occurrence',
foreign_key: :invalidated_by_allocation_id,
inverse_of: :invalidated_by_allocation

#occurrencesActiveRecord::Associations::CollectionProxy<Occurrence> (readonly)

Materialized occurrences projected from this allocation.

Returns:

  • (ActiveRecord::Associations::CollectionProxy<Occurrence>)


71
# File 'app/models/whittaker_tech/aeon/allocation.rb', line 71

has_many :occurrences, inverse_of: :allocation

#schedulableObject

The host record this allocation governs (polymorphic).



49
# File 'app/models/whittaker_tech/aeon/allocation.rb', line 49

belongs_to :schedulable, polymorphic: true

#superseded_allocationAllocation?

The predecessor allocation that this one replaces (fork lineage).

Returns:



54
55
56
57
58
# File 'app/models/whittaker_tech/aeon/allocation.rb', line 54

belongs_to :superseded_allocation,
class_name: 'WhittakerTech::Aeon::Allocation',
foreign_key: :supersedes_allocation_id,
inverse_of: :superseding_allocation,
optional: true

#superseding_allocationAllocation? (readonly)

The successor allocation that replaced this one, if any.

Returns:



63
64
65
66
# File 'app/models/whittaker_tech/aeon/allocation.rb', line 63

has_one :superseding_allocation,
class_name: 'WhittakerTech::Aeon::Allocation',
foreign_key: :supersedes_allocation_id,
inverse_of: :superseded_allocation

#temporal_kindString

Returns one of +“instant”+, +“span”+, or +“schedule”+.

Returns:

  • (String)

    one of +“instant”+, +“span”+, or +“schedule”+



27
# File 'app/models/whittaker_tech/aeon/allocation.rb', line 27

enum :temporal_kind, { instant: 0, span: 1, schedule: 2 }