Module: Menuconform::Rules::NameRules

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

Overview

NAME-001..003: naming quality of customer-facing entities.

Constant Summary collapse

JUNK_TOKENS =
/\b(86|dnu|do not use|do not sell|test|void|zzz+)\b/i

Class Method Summary collapse

Class Method Details

.call(menu) ⇒ Object



11
12
13
# File 'lib/menuconform/rules/name_rules.rb', line 11

def call(menu)
  empty_names(menu) + duplicate_names(menu) + junk_names(menu)
end

.duplicate_names(menu) ⇒ Object

Scopes: item names within one category; modifier names within one group. Every occurrence after the first (in listing order) is flagged.



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/menuconform/rules/name_rules.rb', line 33

def duplicate_names(menu)
  out = {}
  menu.categories_by_id.each_value do |c|
    seen = {}
    (c["item_ids"] || []).each do |iid|
      it = menu.items_by_id[iid]
      next unless it
      key = normalize(it["name"])
      next if key.empty?
      if seen.key?(key) && seen[key] != iid
        out[["item", iid]] ||= Finding.new("NAME-002", "item", iid,
                                           "name duplicates '#{seen[key]}' in category #{c['id']} (case-insensitive)")
      else
        seen[key] ||= iid
      end
    end
  end
  menu.groups_by_id.each_value do |g|
    seen = {}
    (g["options"] || []).each do |o|
      m = menu.modifiers_by_id[o["modifier_id"]]
      next unless m
      key = normalize(m["name"])
      next if key.empty?
      if seen.key?(key) && seen[key] != m["id"]
        out[["modifier", m["id"]]] ||= Finding.new("NAME-002", "modifier", m["id"],
                                                   "name duplicates '#{seen[key]}' in group #{g['id']} (case-insensitive)")
      else
        seen[key] ||= m["id"]
      end
    end
  end
  out.values
end

.each_named_entity(menu) ⇒ Object



15
16
17
18
19
20
# File 'lib/menuconform/rules/name_rules.rb', line 15

def each_named_entity(menu)
  menu.categories_by_id.each_value { |e| yield e, "category" }
  menu.items_by_id.each_value { |e| yield e, "item" }
  menu.groups_by_id.each_value { |e| yield e, "modifier_group" }
  menu.modifiers_by_id.each_value { |e| yield e, "modifier" }
end

.empty_names(menu) ⇒ Object



22
23
24
25
26
27
28
29
# File 'lib/menuconform/rules/name_rules.rb', line 22

def empty_names(menu)
  out = []
  each_named_entity(menu) do |e, type|
    next unless (e["name"] || "").strip.empty?
    out << Finding.new("NAME-001", type, e["id"], "name is empty or whitespace-only")
  end
  out
end

.junk_names(menu) ⇒ Object



68
69
70
71
72
73
74
75
76
77
# File 'lib/menuconform/rules/name_rules.rb', line 68

def junk_names(menu)
  out = []
  each_named_entity(menu) do |e, type|
    name = e["name"] || ""
    next if name.strip.empty? || !name.match?(JUNK_TOKENS)
    out << Finding.new("NAME-003", type, e["id"],
                       "customer-facing name '#{name}' carries back-of-house tokens")
  end
  out
end

.normalize(name) ⇒ Object



79
80
81
# File 'lib/menuconform/rules/name_rules.rb', line 79

def normalize(name)
  (name || "").strip.downcase
end