class Accessory::Accessors::BetweenEachAccessor

Traverses the positions “between” the elements of an Enumerable, including the positions at the “edges” (i.e. before the first, and after the last.)

BetweenEachAccessor can be used with {Lens#put_in} to insert new elements into an Enumerable between the existing ones.

Aliases

Default constructor used by predecessor accessor

Public Instance Methods

ensure_valid(traversal_result) click to toggle source

@!visibility private

# File lib/accessory/accessors/between_each_accessor.rb, line 21
def ensure_valid(traversal_result)
  if traversal_result.kind_of?(Enumerable)
    traversal_result
  else
    []
  end
end
get(data) { |rec| ... } click to toggle source

Feeds {TraversalPosition::EnumerableBeforeOffset}s representing the positions between the elements of data down the accessor chain.

@param data [Enumerable] the Enumerable to iterate through @return [Array] the generated {TraversalPosition::EnumerableBeforeOffset}s

# File lib/accessory/accessors/between_each_accessor.rb, line 52
def get(data)
  positions = traverse_or_default(data || [])

  if block_given?
    positions.map{ |rec| yield(rec) }
  else
    positions
  end
end
get_and_update(data) { |pos| ... } click to toggle source

Feeds {TraversalPosition::EnumerableBeforeOffset}s representing the positions between the elements of data down the accessor chain, manipulating data using the results.

If a new element is returned up the accessor chain, the element is inserted between the existing elements.

If :pop is returned up the accessor chain, no new element is added.

@param data [Enumerable] the Enumerable to iterate through @return [Array] a two-element array containing

1. the {TraversalPosition::EnumerableBeforeOffset}s
2. the new {data}
# File lib/accessory/accessors/between_each_accessor.rb, line 75
def get_and_update(data)
  results = []
  new_data = []
  dirty = false

  positions = traverse_or_default(data || [])

  positions.each do |pos|
    case yield(pos)
    in [:clean, result, _]
      results.push(result)
    in [:dirty, result, new_value]
      new_data.push(new_value)
      results.push(result)
      dirty = true
    in :pop
      # ok
    end

    unless pos.last?
      new_data.push(pos.elem_after)
    end
  end

  if dirty
    [:dirty, results, new_data]
  else
    [:clean, results, data]
  end
end
inspect_args() click to toggle source

@!visibility private

# File lib/accessory/accessors/between_each_accessor.rb, line 30
def inspect_args; nil; end
traverse(data) click to toggle source

@!visibility private

# File lib/accessory/accessors/between_each_accessor.rb, line 33
def traverse(data)
  data_len = data.length

  positions = [
    (0..data_len).to_a,
    data + [nil],
    [nil] + data
  ]

  positions.transpose.map do |(i, b, a)|
    Accessory::TraversalPosition::EnumerableBeforeOffset.new(i, b, a, is_first: i == 0, is_last: i == data_len)
  end
end