Module: Menuconform::Rules::StructRules

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

Overview

STRUCT-002..008. STRUCT-001 (schema validity) runs in the engine before any rule sees the document.

Class Method Summary collapse

Class Method Details

.call(menu) ⇒ Object



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

def call(menu)
  dangling_refs(menu) + duplicate_ids(menu) + orphans(menu) +
    nesting_depth(menu) + uncategorized_items(menu) + empty_categories(menu)
end

.dangling_refs(menu) ⇒ Object



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/menuconform/rules/struct_rules.rb', line 15

def dangling_refs(menu)
  out = {}
  add = lambda do |type, id, missing, what|
    out[[type, id, missing]] ||=
      Finding.new("STRUCT-002", type, id, "references #{what} #{missing}, which is not defined")
  end
  menu.categories.each do |c|
    (c["item_ids"] || []).each do |iid|
      add.call("category", c["id"], iid, "item") unless menu.items_by_id.key?(iid)
    end
  end
  menu.items.each do |it|
    menu.attached_group_ids(it).each do |gid|
      add.call("item", it["id"], gid, "modifier group") unless menu.groups_by_id.key?(gid)
    end
  end
  menu.modifier_groups.each do |g|
    (g["options"] || []).each do |o|
      add.call("modifier_group", g["id"], o["modifier_id"], "modifier") unless menu.modifiers_by_id.key?(o["modifier_id"])
      (o["child_modifier_group_ids"] || []).each do |cgid|
        add.call("modifier_group", g["id"], cgid, "child modifier group") unless menu.groups_by_id.key?(cgid)
      end
      (o["conditional_prices"] || []).each do |cp|
        wid = cp["when_modifier_id"]
        add.call("modifier_group", g["id"], wid, "conditional-price trigger modifier") unless menu.modifiers_by_id.key?(wid)
      end
    end
  end
  out.values
end

.duplicate_ids(menu) ⇒ Object



46
47
48
49
50
# File 'lib/menuconform/rules/struct_rules.rb', line 46

def duplicate_ids(menu)
  menu.duplicate_ids.flat_map do |type, ids|
    ids.map { |id| Finding.new("STRUCT-003", type, id, "more than one #{type} entry shares this id") }
  end
end

.empty_categories(menu) ⇒ Object



87
88
89
90
91
92
# File 'lib/menuconform/rules/struct_rules.rb', line 87

def empty_categories(menu)
  menu.categories_by_id.each_value.filter_map do |c|
    next unless (c["item_ids"] || []).empty?
    Finding.new("STRUCT-008", "category", c["id"], "category lists no items")
  end
end

.nesting_depth(menu) ⇒ Object



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

def nesting_depth(menu)
  menu.items_by_id.each_value.filter_map do |it|
    info = menu.depth_info(it)
    if info[:cyclic]
      Finding.new("STRUCT-005", "item", it["id"], "modifier group nesting contains a cycle")
    elsif info[:max_depth] > 6
      Finding.new("STRUCT-005", "item", it["id"], "modifier group nesting depth #{info[:max_depth]} exceeds 6")
    elsif info[:max_depth] > 4
      Finding.new("STRUCT-006", "item", it["id"], "modifier group nesting depth #{info[:max_depth]} exceeds 4")
    end
  end
end

.orphans(menu) ⇒ Object

Orphan groups and modifiers. Items get STRUCT-007 instead.



53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/menuconform/rules/struct_rules.rb', line 53

def orphans(menu)
  out = []
  menu.groups_by_id.each_value do |g|
    next if menu.referenced_group_ids.include?(g["id"])
    out << Finding.new("STRUCT-004", "modifier_group", g["id"], "defined but referenced by nothing")
  end
  menu.modifiers_by_id.each_value do |m|
    next if menu.referenced_modifier_ids.include?(m["id"])
    out << Finding.new("STRUCT-004", "modifier", m["id"], "defined but referenced by nothing")
  end
  out
end

.uncategorized_items(menu) ⇒ Object



79
80
81
82
83
84
85
# File 'lib/menuconform/rules/struct_rules.rb', line 79

def uncategorized_items(menu)
  listed = menu.categories.flat_map { |c| c["item_ids"] || [] }.to_set
  menu.items_by_id.each_value.filter_map do |it|
    next if listed.include?(it["id"])
    Finding.new("STRUCT-007", "item", it["id"], "not listed in any category")
  end
end