class ViewModel::ActiveRecord::UpdateOperation::MutableReferencedCollection

‘orphaned_members`.“
update operation. Elements removed from the collection are collected as
provide update operations. No one member may be affected by more than one
Helper class to wrap the previous members of a referenced collection and

def claim_existing_member(indirect_vm_ref, ref_string = nil)

Claim an existing collection member for the update and optionally set its ref.
def claim_existing_member(indirect_vm_ref, ref_string = nil)
  member = free_members_by_indirect_ref.delete(indirect_vm_ref) do
    raise ViewModel::DeserializationError::AssociatedNotFound.new(
      association_data.association_name.to_s, indirect_vm_ref, blame_reference)
  end
  member.ref_string = ref_string if ref_string
  member
end

def claim_existing_references(references)

Reclaim existing members corresponding to the specified references or raise if not found.
def claim_existing_references(references)
  references.each do |ref_string|
    indirect_vm_ref = update_context.resolve_reference(ref_string, blame_reference).viewmodel_reference
    claim_existing_member(indirect_vm_ref, ref_string)
  end
end

def claim_or_create_member(indirect_vm_ref, ref_string)

Reclaim an existing member for an update and set its ref, or create a new one if not found.
def claim_or_create_member(indirect_vm_ref, ref_string)
  member = free_members_by_indirect_ref.delete(indirect_vm_ref) do
    ReferencedCollectionMember.new(indirect_vm_ref, association_data.direct_viewmodel.for_new_model)
  end
  member.ref_string = ref_string
  member
end

def claim_or_create_references(references)

Reclaim existing members corresponding to the specified references, or create new ones if not found.
def claim_or_create_references(references)
  references.map do |ref_string|
    indirect_vm_ref = update_context.resolve_reference(ref_string, blame_reference).viewmodel_reference
    claim_or_create_member(indirect_vm_ref, ref_string)
  end
end

def concat(references)

def concat(references)
  new_members = claim_or_create_references(references)
  remove_from_members(new_members)
  members.concat(new_members)
end

def initialize(association_data, update_context, members, blame_reference)

def initialize(association_data, update_context, members, blame_reference)
  @association_data = association_data
  @update_context   = update_context
  @members          = members.dup
  @blame_reference  = blame_reference
  @orphaned_members = []
  @free_members_by_indirect_ref = @members.index_by(&:indirect_viewmodel_reference)
end

def insert_after(relative_to, references)

def insert_after(relative_to, references)
  insert_relative(relative_to, 1, references)
end

def insert_before(relative_to, references)

def insert_before(relative_to, references)
  insert_relative(relative_to, 0, references)
end

def insert_relative(relative_vm_ref, offset, references)

def insert_relative(relative_vm_ref, offset, references)
  new_members = claim_or_create_references(references)
  remove_from_members(new_members)
  index = members.find_index { |m| m.indirect_viewmodel_reference == relative_vm_ref }
  unless index
    raise ViewModel::DeserializationError::AssociatedNotFound.new(
      association_data.association_name.to_s, relative_vm_ref, blame_reference)
  end
  members.insert(index + offset, *new_members)
end

def remove(vm_references)

def remove(vm_references)
  removed_members = vm_references.map do |vm_ref|
    claim_existing_member(vm_ref)
  end
  remove_from_members(removed_members)
  orphaned_members.concat(removed_members)
end

def remove_from_members(removed_members)

def remove_from_members(removed_members)
  s = removed_members.to_set
  members.reject! { |m| s.include?(m) }
end

def replace(references)

def replace(references)
  members.replace(claim_or_create_references(references))
  # Any unclaimed free members after building the update target are now
  # orphaned and their direct viewmodels can be released.
  orphaned_members.concat(free_members_by_indirect_ref.values)
  free_members_by_indirect_ref.clear
end

def update(references)

def update(references)
  claim_existing_references(references)
end