Module: Menuconform::Rules::AgeRules

Defined in:
lib/menuconform/rules/age_rules.rb

Overview

AGE-001..002. AGE-001 is a name heuristic by necessity: menus don't label alcohol, which is exactly the problem. The exclusion list guards the known soda/dessert traps (root beer, ginger ale, rum raisin); keep both lists tight — a false 'unlabeled alcohol' error costs the report credibility.

Constant Summary collapse

ALCOHOL =
/\b(margarita|mojito|daiquiri|sangria|mimosa|bellini|negroni|martini|cocktail|
beer|lager|ale|ipa|stout|porter|pilsner|hefeweizen|
wine|chardonnay|merlot|cabernet|riesling|rose\s+all\s+day|prosecco|champagne|
whiskey|whisky|bourbon|scotch|vodka|tequila|mezcal|rum|gin|brandy|cognac|
liqueur|sake|soju|cider|hard\s+seltzer)\b/xi
EXCLUSIONS =
/root\s+beer|ginger\s+ale|ginger\s+beer|birch\s+beer|butter\s*beer|
rum\s+(raisin|cake)|beer\s*battered|beer\s*cheese|
non.?alcoholic|alcohol.?free|virgin|0\.0/xi
KIDS_CATEGORY =
/\bkids?\b|\bchild(ren)?\b|\bjunior\b|\blittle\b/i

Class Method Summary collapse

Class Method Details

.alcohol_indicative?(name) ⇒ Boolean

Returns:

  • (Boolean)


26
27
28
29
# File 'lib/menuconform/rules/age_rules.rb', line 26

def alcohol_indicative?(name)
  n = name || ""
  n.match?(ALCOHOL) && !n.match?(EXCLUSIONS)
end

.call(menu) ⇒ Object



22
23
24
# File 'lib/menuconform/rules/age_rules.rb', line 22

def call(menu)
  unlabeled_alcohol(menu) + kids_category_conflicts(menu)
end

.kids_category_conflicts(menu) ⇒ Object



41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/menuconform/rules/age_rules.rb', line 41

def kids_category_conflicts(menu)
  out = {}
  menu.categories_by_id.each_value do |c|
    next unless (c["name"] || "").match?(KIDS_CATEGORY)
    (c["item_ids"] || []).each do |iid|
      it = menu.items_by_id[iid]
      next unless it
      next unless it["min_age"] || alcohol_indicative?(it["name"])
      out[iid] ||= Finding.new("AGE-002", "item", iid,
                               "age-restricted or alcohol-indicative item listed in kids-oriented category #{c['id']}")
    end
  end
  out.values
end

.unlabeled_alcohol(menu) ⇒ Object



31
32
33
34
35
36
37
38
39
# File 'lib/menuconform/rules/age_rules.rb', line 31

def unlabeled_alcohol(menu)
  check = lambda do |entity, type|
    return nil if entity["min_age"] || !alcohol_indicative?(entity["name"])
    Finding.new("AGE-001", type, entity["id"],
                "name '#{entity['name']}' indicates alcohol but no min_age is set")
  end
  menu.items_by_id.each_value.filter_map { |it| check.call(it, "item") } +
    menu.modifiers_by_id.each_value.filter_map { |m| check.call(m, "modifier") }
end