Class: SqlChatbot::Services::RegistryBuilder
- Inherits:
-
Object
- Object
- SqlChatbot::Services::RegistryBuilder
- Defined in:
- lib/sql_chatbot/services/registry_builder.rb
Constant Summary collapse
- SOFT_DELETE_COLS =
%w[deleted_at discarded_at archived_at removed_at].freeze
- SYNONYM_GROUPS =
Conservative domain-synonym aliasing. Mirror of TS applyDomainSynonyms in registry-loader.ts. For each synonym group, only register the rest of the group as aliases when exactly ONE entity claims a group member (via canonical name OR an existing alias) — avoids the “customer and user are both real entities” ambiguity.
[ %w[ticket tickets conversation conversations chat chats], %w[order orders purchase purchases transaction transactions], %w[post posts article articles entry entries], # Code repositories — does NOT include project/projects. Apps with # both `repository` and `project` tables (Gitea) would split the # group's claim and the entire group would skip via the single- # claimer rule. Code review on V1.3-R caught this. %w[repo repos repository repositories], %w[issue issues bug bugs task tasks], # Messaging / communication channels — Chatwoot uses `inbox`, # Slack-style apps use `channel`. Single-claimer rule handles # apps that have only one of the two as a real entity. %w[channel channels inbox inboxes], ].freeze
Instance Method Summary collapse
-
#apply_custom_aliases!(registry) ⇒ Object
Merge developer-supplied aliases.
- #apply_domain_synonyms!(registry) ⇒ Object
- #build ⇒ Object
-
#build_entity_aliases(entities) ⇒ Object
Build aliases that map common question phrasings to canonical entity names.
-
#initialize(default_filters: nil, custom_aliases: nil) ⇒ RegistryBuilder
constructor
A new instance of RegistryBuilder.
- #pluralize_simple(word) ⇒ Object
Constructor Details
#initialize(default_filters: nil, custom_aliases: nil) ⇒ RegistryBuilder
Returns a new instance of RegistryBuilder.
11 12 13 14 |
# File 'lib/sql_chatbot/services/registry_builder.rb', line 11 def initialize(default_filters: nil, custom_aliases: nil) @default_filters = default_filters || {} @custom_aliases = custom_aliases || {} end |
Instance Method Details
#apply_custom_aliases!(registry) ⇒ Object
Merge developer-supplied aliases. Custom mappings always WIN — they override auto-detected aliases on conflict. Silently skips entries whose target entity doesn’t exist in the registry (typo in config or stale config after schema change).
80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/sql_chatbot/services/registry_builder.rb', line 80 def apply_custom_aliases!(registry) return if @custom_aliases.nil? || @custom_aliases.empty? @custom_aliases.each do |raw_alias, raw_target| alias_term = raw_alias.to_s.downcase.strip target = raw_target.to_s.strip next if alias_term.empty? || target.empty? next unless registry.entities.key?(target) next if registry.entities.key?(alias_term) registry.aliases[alias_term] = target end end |
#apply_domain_synonyms!(registry) ⇒ Object
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
# File 'lib/sql_chatbot/services/registry_builder.rb', line 53 def apply_domain_synonyms!(registry) SYNONYM_GROUPS.each do |group| claiming = Set.new group.each do |member| lc = member.downcase if registry.entities.key?(lc) claiming << lc next end target = registry.aliases[lc] claiming << target if target end next unless claiming.size == 1 target = claiming.first group.each do |member| lc = member.downcase next if registry.entities.key?(lc) next if registry.aliases.key?(lc) registry.aliases[lc] = target end end end |
#build ⇒ Object
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
# File 'lib/sql_chatbot/services/registry_builder.rb', line 16 def build entities = {} discover_models.each do |model| entity_name = model.name.underscore entities[entity_name] = build_entity(model, entity_name) end registry = Grammar::Registry.new( framework: "rails", entities: entities, aliases: build_entity_aliases(entities), ) apply_domain_synonyms!(registry) apply_custom_aliases!(registry) registry end |
#build_entity_aliases(entities) ⇒ Object
Build aliases that map common question phrasings to canonical entity names. Rules (no clash with a real canonical entity name):
multi-word form (spaces) → snake_case entity name
"service areas" → "service_area"
plural form → singular entity name
"users" / "customers" → already handled by string-match scoring,
but we also explicitly map plural-snake → canonical
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
# File 'lib/sql_chatbot/services/registry_builder.rb', line 99 def build_entity_aliases(entities) aliases = {} # Process simpler names first so they get first dibs on auto-aliases. # Without this, `account_user` (2 segments) could claim `account_users` # before `user` (1 segment) had a chance to claim its own plural. ordered_names = entities.keys.sort_by { |n| [n.split("_").length, n] } ordered_names.each do |name| # "service_area" → "service areas", "service area", "service_areas" spaced = name.tr("_", " ") spaced_plu = pluralize_simple(spaced) snake_plu = pluralize_simple(name) [spaced, spaced_plu, snake_plu].each do |alt| next if alt == name next if entities.key?(alt) next if aliases.key?(alt) aliases[alt] = name end end aliases end |
#pluralize_simple(word) ⇒ Object
120 121 122 123 124 |
# File 'lib/sql_chatbot/services/registry_builder.rb', line 120 def pluralize_simple(word) return word + "es" if word.end_with?("s", "x", "ch", "sh") return word[0..-2] + "ies" if word.end_with?("y") && !%w[a e i o u].include?(word[-2]) word + "s" end |