class Enumpath::Operator::SubscriptExpression

Implements JSONPath subscript expressions operator syntax. See {file:README.md#label-Subscript+expressions+operator} for syntax and examples

Constants

ARITHMETIC_OPERATOR_REGEX
OPERATOR_REGEX

Public Class Methods

detect?(operator) click to toggle source

Whether the operator matches {Enumpath::Operator::SubscriptExpression::OPERATOR_REGEX}

@param operator (see Enumpath::Operator::Base.detect?) @return (see Enumpath::Operator::Base.detect?)

# File lib/enumpath/operator/subscript_expression.rb, line 16
def detect?(operator)
  !(operator =~ OPERATOR_REGEX).nil?
end

Public Instance Methods

apply(remaining_path, enum, resolved_path) { |remaining_path, value, resolved_path + [result]| ... } click to toggle source

Yields to the block once if the subscript expression evaluates to a member of the enumerable

@param (see Enumpath::Operator::Base#apply) @yield (see Enumpath::Operator::Base#apply) @yieldparam remaining_path [Array] remaining_path @yieldparam enum [Enumerable] the member of the enumerable at the value of the subscript expression @yieldparam resolved_path [Array] resolved_path plus the value of the subscript expression

# File lib/enumpath/operator/subscript_expression.rb, line 28
def apply(remaining_path, enum, resolved_path)
  Enumpath.log('Applying subscript expression') { { expression: operator, to: enum } }

  _match, unpacked_operator = OPERATOR_REGEX.match(operator).to_a
  result = evaluate(unpacked_operator, enum)

  value = Enumpath::Resolver::Simple.resolve(result, enum)
  Enumpath.log('Applying subscript') { { 'enum at subscript': value } } unless value.nil?
  yield(remaining_path, value, resolved_path + [result.to_s]) unless value.nil?
end

Private Instance Methods

evaluate(unpacked_operator, enum) click to toggle source
# File lib/enumpath/operator/subscript_expression.rb, line 41
def evaluate(unpacked_operator, enum)
  property, operator, operand = unpacked_operator.split(ARITHMETIC_OPERATOR_REGEX).map(&:strip)
  test(operator, operand, resolve(property, enum))
end
evaluate_with_operator(operator, operand, value) click to toggle source
# File lib/enumpath/operator/subscript_expression.rb, line 66
def evaluate_with_operator(operator, operand, value)
  typecast_operand = variable_typecaster(operand)
  result = value.public_send(operator.to_sym, typecast_operand)
  Enumpath.log('Evaluated subscript') do
    { value: value, operator: operator, operand: typecast_operand, result: result }
  end
  result
end
resolve(property, enum) click to toggle source
# File lib/enumpath/operator/subscript_expression.rb, line 46
def resolve(property, enum)
  return enum if property == '@'

  value = Enumpath::Resolver::Simple.resolve(property.gsub(/^@\./, ''), enum)
  value = Enumpath::Resolver::Property.resolve(property.gsub(/^@\./, ''), enum) if value.nil?
  value
end
test(operator, operand, value) click to toggle source
# File lib/enumpath/operator/subscript_expression.rb, line 54
def test(operator, operand, value)
  if operator.nil? || operand.nil?
    Enumpath.log('Simple subscript') { { subscript: value } }
    value
  else
    evaluate_with_operator(operator, operand, value)
  end
rescue NoMethodError
  Enumpath.log('Subscript could not be evaluated') { { subscript: nil } }
  nil
end
variable_typecaster(variable) click to toggle source
# File lib/enumpath/operator/subscript_expression.rb, line 75
def variable_typecaster(variable)
  if variable =~ /\A('|").+\1\z/ || variable =~ /^:.+/
    # It quacks like a string or symbol
    variable.gsub(/\A(:|('|"))|('|")\z/, '')
  else
    # Otherwise treat it as a number. Note that we only care about whole numbers in this case
    variable.to_i
  end
end