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)
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)
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)
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)
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