class FoodIngredientParser::Loose::Transform::HandleMissingName

Transforms node tree to handle missing names.

The loose parser can return a node tree that has some ingredients without a name. Usually this means that either the parser wasn't smart enough to understand the input, or the input was not strictly clear (e.g. a case like “herbs, (oregano), salt” is often seen).

When a contained node is found which doesn't have a name:

Public Class Methods

new(node) click to toggle source
# File lib/food_ingredient_parser/loose/transform/handle_missing_name.rb, line 27
def initialize(node)
  @node = node
end
transform!(node) click to toggle source
# File lib/food_ingredient_parser/loose/transform/handle_missing_name.rb, line 23
def self.transform!(node)
  new(node).transform!
end

Public Instance Methods

transform!() click to toggle source
# File lib/food_ingredient_parser/loose/transform/handle_missing_name.rb, line 31
def transform!
  transform_children!(@node)
  @node
end

Private Instance Methods

transform_children!(node) click to toggle source
# File lib/food_ingredient_parser/loose/transform/handle_missing_name.rb, line 38
def transform_children!(node)
  prev = nil
  new_contains = []
  node.contains.each do |child|
    # Apply recursively. Do it before processing to handle multiple depth levels of missing names.
    transform_children!(child) if child.contains.any?

    if child.name.nil? || child.name.text_value.strip == ''
      # Name is empty, we need to do something.
      if prev
        # there is a previous ingredient: move children to new parent
        prev.contains.push(*child.contains)
      elsif child.mark && !node.mark && child.contains.empty? && !child.amount
        # this is just a mark without siblings: it's a mark for its parent
        node.mark = child.mark
      else
        # there is no previous ingredient: move children one level up
        new_contains.push(*child.contains)
      end
    else
      # Nothing to see here, just leave it as it is.
      new_contains << child
    end

    prev = child
  end

  node.contains = new_contains
end