Class: Munola::Detector

Inherits:
Object
  • Object
show all
Defined in:
lib/munola/detector.rb

Overview

Reads the tree for what the binary's own init cannot see: which catalogue recipes have the directories their roles need, and which column most tables share. It reads files; it never asks.

Defined Under Namespace

Classes: Tenant

Instance Method Summary collapse

Constructor Details

#initialize(root) ⇒ Detector

Returns a new instance of Detector.



10
11
12
# File 'lib/munola/detector.rb', line 10

def initialize(root)
  @root = File.expand_path(root)
end

Instance Method Details

#bindingsObject



14
15
16
17
18
19
20
21
# File 'lib/munola/detector.rb', line 14

def bindings
  found = []
  found << "ember-conventions" if file?("ember-cli-build.js")
  found << "data-ownership" if schema? && dir?("app/models")
  found << "api-boundaries" if file?("config/routes.rb") && dir?("app/policies")
  found << "background-work" if dir?("app/tasks")
  found
end

#schema?Boolean

Returns:

  • (Boolean)


23
24
25
# File 'lib/munola/detector.rb', line 23

def schema?
  file?("db/schema.rb") || file?("db/structure.sql")
end

#tenant(column: nil) ⇒ Object

The tenant column is the one present on most tables; a column the caller names is confirmed against the schema rather than trusted.



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/munola/detector.rb', line 29

def tenant(column: nil)
  tables = schema_tables
  return nil if tables.empty?

  counts = Hash.new(0)
  tables.each_value { |columns| columns.uniq.each { |name| counts[name] += 1 } }
  candidate = column || counts.select { |name, _| name.end_with?("_id") }.max_by { |name, count| [count, -name.length] }&.first
  return nil unless candidate

  share = counts.fetch(candidate, 0).fdiv(tables.size)
  return nil if share < 0.5 && column.nil?

  table = tenant_table(candidate, tables.keys)
  Tenant.new(column: candidate, table: table, share: share)
end