Class: EagerEye::Detectors::LoopAssociation

Inherits:
Base
  • Object
show all
Defined in:
lib/eager_eye/detectors/loop_association.rb

Constant Summary collapse

ITERATION_METHODS =
%i[each map collect select find find_all reject filter filter_map flat_map].freeze
PRELOAD_METHODS =
%i[includes preload eager_load].freeze
SINGULAR_ASSOCIATIONS =

Common singular association names (belongs_to pattern)

%w[
  author user owner creator admin member customer client
  post article comment category tag parent company organization
  project task item order product account profile setting
  image avatar photo attachment document
].freeze
PLURAL_ASSOCIATIONS =

Common plural association names (has_many pattern)

%w[
  authors users owners creators admins members customers clients
  posts articles comments categories tags children companies organizations
  projects tasks items orders products accounts profiles settings
  images avatars photos attachments documents
].freeze
EXCLUDED_METHODS =

Methods that should NOT be treated as associations

%i[
  id to_s to_h to_a to_json to_xml inspect class object_id nil? blank? present? empty?
  any? none? size count length save save! update update! destroy destroy! delete delete!
  valid? invalid? errors new? persisted? changed? frozen? name title body content text
  description value key type status state created_at updated_at deleted_at
].freeze

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.detector_nameObject



33
34
35
# File 'lib/eager_eye/detectors/loop_association.rb', line 33

def self.detector_name
  :loop_association
end

Instance Method Details

#detect(ast, file_path) ⇒ Object



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/eager_eye/detectors/loop_association.rb', line 37

def detect(ast, file_path)
  return [] unless ast

  issues = []

  # Build a map of variable names to their preloaded associations
  @variable_preloads = build_variable_preloads_map(ast)

  traverse_ast(ast) do |node|
    next unless iteration_block?(node)

    block_var = extract_block_variable(node)
    next unless block_var

    block_body = node.children[2]
    next unless block_body

    # Check if the collection already has includes (both chained and from variable assignment)
    collection_node = node.children[0]
    included_associations = extract_included_associations(collection_node)

    # Also check if the collection comes from a variable that was assigned with preloads
    variable_preloads = extract_variable_preloads(collection_node)
    included_associations.merge(variable_preloads)

    find_association_calls(block_body, block_var, file_path, issues, included_associations)
  end

  issues
end