Module: RailsAiBridge::ExclusionHelper

Defined in:
lib/rails_ai_bridge/exclusion_helper.rb

Overview

Table name matching for config.excluded_tables (exact names or * globs).

Class Method Summary collapse

Class Method Details

.class_stems(token) ⇒ Array<String>

Table-name candidates for a class or route/controller token.

Parameters:

  • token (String)

Returns:

  • (Array<String>)


82
83
84
85
86
87
88
89
90
91
# File 'lib/rails_ai_bridge/exclusion_helper.rb', line 82

def class_stems(token)
  pieces = [token, token.split('::').last].compact
  pieces << pieces.last.to_s.delete_suffix('Controller')
  pieces.flat_map do |piece|
    next [] if piece.empty?

    snake = piece.underscore
    [snake, snake.pluralize, snake.singularize]
  end.uniq
end

.classify_base(name) ⇒ String

Parameters:

  • name (String)

Returns:

  • (String)


74
75
76
# File 'lib/rails_ai_bridge/exclusion_helper.rb', line 74

def classify_base(name)
  name.to_s.demodulize.delete_suffix('Controller').singularize.camelize
end

.excluded_class_or_table?(name, config) ⇒ Boolean

Returns true when name is an excluded model or maps to an excluded table. Accepts rubydex-decorated tokens such as PatientRecord::<PatientRecord>. Demodulized bases match only when the module prefix is the same (+User+ vs UsersController, not User vs Admin::User).

Parameters:

  • name (String, nil)

    class, association, controller, or route token

  • config (#excluded_models, #excluded_table?)

Returns:

  • (Boolean)


31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/rails_ai_bridge/exclusion_helper.rb', line 31

def excluded_class_or_table?(name, config)
  token = normalize_class_token(name)
  return false if token.empty?

  if config.respond_to?(:excluded_models)
    models = Array(config.excluded_models).map(&:to_s)
    return true if models.any? { |excluded| token == excluded || token.start_with?("#{excluded}::") }
    return true if models.any? { |excluded| namespaced_base_match?(token, excluded) }
  end

  return false unless config.respond_to?(:excluded_table?)

  class_stems(token).any? { |stem| config.excluded_table?(stem) }
end

.module_prefix(name) ⇒ String

Parameters:

  • name (String)

Returns:

  • (String)


68
69
70
# File 'lib/rails_ai_bridge/exclusion_helper.rb', line 68

def module_prefix(name)
  name.to_s.deconstantize
end

.namespaced_base_match?(token, excluded) ⇒ Boolean

True when demodulized bases match and both tokens share a module prefix.

Parameters:

  • token (String)
  • excluded (String)

Returns:

  • (Boolean)


60
61
62
63
64
# File 'lib/rails_ai_bridge/exclusion_helper.rb', line 60

def namespaced_base_match?(token, excluded)
  return false unless module_prefix(token).casecmp?(module_prefix(excluded))

  classify_base(token) == classify_base(excluded)
end

.normalize_class_token(name) ⇒ String

Strips rubydex decoration (+Class::+) from a related-model token and normalizes route-style admin/users paths to admin::users.

Parameters:

  • name (String, nil)

Returns:

  • (String)


51
52
53
# File 'lib/rails_ai_bridge/exclusion_helper.rb', line 51

def normalize_class_token(name)
  name.to_s.sub(/::<[^>]*>\z/, '').gsub('/', '::')
end

.table_pattern_match?(pattern, table_name) ⇒ Boolean

Returns true when table_name matches pattern exactly or via * glob. Table names in Rails are always lowercase snake_case, so matching is case-sensitive.

Parameters:

  • pattern (String)

    exact name (e.g. "secrets") or glob (e.g. "audit_*")

  • table_name (String)

    lowercase table name to test

Returns:

  • (Boolean)


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

def table_pattern_match?(pattern, table_name)
  return false if pattern.to_s.empty? || table_name.to_s.empty?

  pat = pattern.to_s
  return pat == table_name unless pat.include?('*')

  File.fnmatch(pat, table_name, File::FNM_EXTGLOB)
end