class FoodIngredientParser::Loose::Transform::Amount

Transforms node tree to extract amount into its own attribute.

Public Class Methods

new(node) click to toggle source
# File lib/food_ingredient_parser/loose/transform/amount.rb, line 17
def initialize(node)
  @node = node
  @parser = FoodIngredientParser::Loose::Transform::AmountFromNameParser.new
end
transform!(node) click to toggle source
# File lib/food_ingredient_parser/loose/transform/amount.rb, line 13
def self.transform!(node)
  new(node).transform!
end

Public Instance Methods

transform!() click to toggle source
# File lib/food_ingredient_parser/loose/transform/amount.rb, line 22
def transform!
  transform_name
  transform_contains
  @node
end

Private Instance Methods

parse_amount(s) click to toggle source
# File lib/food_ingredient_parser/loose/transform/amount.rb, line 65
def parse_amount(s)
  @parser.parse(s) if s && s.strip != ''
end
transform_contains(node = @node) click to toggle source

If first or last child is an amount, it's this node's amount. Assumes all names already have extracted their amounts with {{#transform_name}}.

# File lib/food_ingredient_parser/loose/transform/amount.rb, line 52
def transform_contains(node = @node)
  if !node.amount && node.contains.any?
    if node.contains.first.name.nil? && node.contains.first.amount
      node.amount = node.contains.shift.amount
    elsif node.contains.count > 1 && node.contains.last.name.nil? && node.contains.last.amount
      node.amount = node.contains.pop.amount
    end
  end

  # recursively transform contained nodes
  node.contains.each(&method(:transform_contains))
end
transform_name(node = @node) click to toggle source

Extract amount from name, if any.

# File lib/food_ingredient_parser/loose/transform/amount.rb, line 31
def transform_name(node = @node)
  if !node.amount && parsed = parse_amount(node.name&.text_value)
    offset = node.name.interval.first

    amount = parsed.amount.amount
    node.amount = Node.new(node.input, offset + amount.interval.first .. offset + amount.interval.last - 1)

    name = parsed.respond_to?(:name) && parsed.name
    if name && name.interval.count > 0
      node.name = Node.new(node.input, offset + name.interval.first .. offset + name.interval.last - 1)
    else
      node.name = nil
    end
  end

  # recursively transform contained nodes
  node.contains&.each(&method(:transform_name))
end