Class: ActiveItem::EmbeddedCollection

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/active_item/embedded_collection.rb

Overview

In-memory collection for embedded model instances. Provides Enumerable access plus ActiveItem-flavored query methods (where, find, build, etc.) that operate on the already-loaded array.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(owner:, association_name:, target_class:, records: []) ⇒ EmbeddedCollection

Returns a new instance of EmbeddedCollection.



14
15
16
17
18
19
# File 'lib/active_item/embedded_collection.rb', line 14

def initialize(owner:, association_name:, target_class:, records: [])
  @owner = owner
  @association_name = association_name
  @target_class = target_class
  @records = records.dup
end

Instance Attribute Details

#association_nameObject (readonly)

Returns the value of attribute association_name.



12
13
14
# File 'lib/active_item/embedded_collection.rb', line 12

def association_name
  @association_name
end

#ownerObject (readonly)

Returns the value of attribute owner.



12
13
14
# File 'lib/active_item/embedded_collection.rb', line 12

def owner
  @owner
end

#recordsObject (readonly)

Returns the value of attribute records.



12
13
14
# File 'lib/active_item/embedded_collection.rb', line 12

def records
  @records
end

#target_classObject (readonly)

Returns the value of attribute target_class.



12
13
14
# File 'lib/active_item/embedded_collection.rb', line 12

def target_class
  @target_class
end

Instance Method Details

#<<(record) ⇒ Object Also known as: push



117
118
119
120
121
122
# File 'lib/active_item/embedded_collection.rb', line 117

def <<(record)
  record.instance_variable_set(:@_embedded_parent, @owner)
  @records << record
  mark_owner_dirty!
  self
end

#any?(&block) ⇒ Boolean

Returns:

  • (Boolean)


35
36
37
# File 'lib/active_item/embedded_collection.rb', line 35

def any?(&block)
  block ? @records.any?(&block) : @records.any?
end

#build(attributes = {}) ⇒ Object

Build a new embedded record, add it to the collection, and mark the parent as dirty.



78
79
80
81
82
83
84
85
# File 'lib/active_item/embedded_collection.rb', line 78

def build(attributes = {})
  record = @target_class.new(attributes)
  record.instance_variable_set(:@id, SecureRandom.uuid) unless record.id
  record.instance_variable_set(:@_embedded_parent, @owner)
  @records << record
  mark_owner_dirty!
  record
end

#create!(attributes = {}) ⇒ Object

Build, validate, and persist by saving the parent. Matches ActiveRecord semantics where create! actually persists.



89
90
91
92
93
94
95
96
97
98
99
# File 'lib/active_item/embedded_collection.rb', line 89

def create!(attributes = {})
  record = build(attributes)
  unless record.valid?
    @records.delete(record)
    mark_owner_dirty!
    raise ActiveItem::RecordInvalid, record
  end

  @owner.save!
  record
end

#delete(record_or_id) ⇒ Object Also known as: destroy

Remove a record from the collection by reference or ID.



102
103
104
105
106
107
# File 'lib/active_item/embedded_collection.rb', line 102

def delete(record_or_id)
  record = record_or_id.is_a?(String) ? find(record_or_id) : record_or_id
  @records.delete(record)
  mark_owner_dirty!
  record
end

#eachObject



21
22
23
# File 'lib/active_item/embedded_collection.rb', line 21

def each(&)
  @records.each(&)
end

#empty?Boolean

Returns:

  • (Boolean)


31
32
33
# File 'lib/active_item/embedded_collection.rb', line 31

def empty?
  @records.empty?
end

#find(id) ⇒ Object

In-memory find by ID.



52
53
54
55
56
57
# File 'lib/active_item/embedded_collection.rb', line 52

def find(id)
  record = @records.find { |r| r.id == id }
  raise ActiveItem::RecordNotFound, "Couldn't find #{@target_class.name} with id '#{id}'" unless record

  record
end

#firstObject



39
40
41
# File 'lib/active_item/embedded_collection.rb', line 39

def first
  @records.first
end

#inspectObject



125
126
127
# File 'lib/active_item/embedded_collection.rb', line 125

def inspect
  "#<#{self.class.name} [#{@records.map(&:inspect).join(', ')}]>"
end

#lastObject



43
44
45
# File 'lib/active_item/embedded_collection.rb', line 43

def last
  @records.last
end

#lengthObject Also known as: size, count



25
26
27
# File 'lib/active_item/embedded_collection.rb', line 25

def length
  @records.length
end

#replace(new_records) ⇒ Object

Replace the entire collection.



111
112
113
114
115
# File 'lib/active_item/embedded_collection.rb', line 111

def replace(new_records)
  @records = new_records.dup
  mark_owner_dirty!
  self
end

#to_aObject



47
48
49
# File 'lib/active_item/embedded_collection.rb', line 47

def to_a
  @records.dup
end

#where(conditions = {}) ⇒ Object

In-memory filtering by attribute conditions. Returns a new EmbeddedCollection with matching records.



61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/active_item/embedded_collection.rb', line 61

def where(conditions = {})
  filtered = @records.select do |record|
    conditions.all? do |attr, value|
      record.send(attr) == value
    end
  end

  self.class.new(
    owner: @owner,
    association_name: @association_name,
    target_class: @target_class,
    records: filtered
  )
end