Module: RailsAiContext::ConcernPaths

Defined in:
lib/rails_ai_context/concern_paths.rb

Overview

One answer to "where does this app keep its concerns", for every surface that lists or counts them.

GetConcern hardcoded two directories and ActiveSupportIntrospector hardcoded five, so a single run answered 80 concerns and 81 concerns for the same app, and the mailer concern only the second one found could not be reached through the first at all. Neither list matches Rails, which autoloads these paths by glob - Rails::Engine::Configuration#paths adds app with glob: "{*,*/concerns}" - so any hardcoded list is one entry behind an app that keeps app/serializers/concerns.

Class Method Summary collapse

Class Method Details

.find_file(root, concern_name) ⇒ Object

Source file for a concern named by its constant, or nil.

Parameters:

  • root (String)

    application root

  • concern_name (String)

    constant name, e.g. "BulkMailSettingsConcern"



47
48
49
50
51
52
53
54
# File 'lib/rails_ai_context/concern_paths.rb', line 47

def find_file(root, concern_name)
  underscore = concern_name.to_s.underscore
  return nil if underscore.empty? || underscore.include?("..")

  resolve(root)
    .map { |dir| File.join(dir, "#{underscore}.rb") }
    .find { |path| File.exist?(path) }
end

.resolve(root) ⇒ Array<String>

Returns absolute concern directories that exist.

Parameters:

  • root (String)

    application root

Returns:

  • (Array<String>)

    absolute concern directories that exist



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/rails_ai_context/concern_paths.rb', line 19

def resolve(root)
  # An app that names its concern directories means those and no others -
  # the setting has to be able to narrow, or it only ever adds noise. It is
  # unset by default, which is what asks for discovery.
  configured = RailsAiContext.configuration.concern_paths
  dirs =
    if configured.nil?
      Dir.glob(File.join(root, "app", "*", "concerns"))
    else
      # A path that is already absolute is taken as given; `File.join`
      # would graft it onto the root and point at nothing.
      Array(configured).map { |rel| File.absolute_path?(rel) ? rel : File.join(root, rel) }
    end

  dirs.uniq.select { |dir| Dir.exist?(dir) }.sort
end

.type_for(dir) ⇒ Object

The owner segment names the type: app/mailers/concerns holds mailer concerns. Singular so a filter reads type: "mailer".



38
39
40
41
# File 'lib/rails_ai_context/concern_paths.rb', line 38

def type_for(dir)
  segment = dir[%r{/app/([^/]+)/concerns/?\z}, 1]
  segment ? segment.singularize : "other"
end