Sha256: 385965fb7840d13ae4a488902fdfd9202b57280afecd8c5a2cfa67e605cd5b86

Contents?: true

Size: 1.49 KB

Versions: 3

Compression:

Stored size: 1.49 KB

Contents

# typed: true
# frozen_string_literal: true

require "packwerk/constant_name_inspector"
require "packwerk/node"

module Packwerk
  # Extracts the implicit constant reference from an active record association
  class AssociationInspector
    include ConstantNameInspector

    RAILS_ASSOCIATIONS = %i(
      belongs_to
      has_many
      has_one
      has_and_belongs_to_many
    ).to_set

    def initialize(inflector:, custom_associations: Set.new)
      @inflector = inflector
      @associations = RAILS_ASSOCIATIONS + custom_associations
    end

    def constant_name_from_node(node, ancestors:)
      return unless Node.method_call?(node)
      return unless association?(node)

      arguments = Node.method_arguments(node)
      return unless (association_name = association_name(arguments))

      if (class_name_node = custom_class_name(arguments))
        return unless Node.string?(class_name_node)
        Node.literal_value(class_name_node)
      else
        @inflector.classify(association_name.to_s)
      end
    end

    private

    def association?(node)
      method_name = Node.method_name(node)
      @associations.include?(method_name)
    end

    def custom_class_name(arguments)
      association_options = arguments.detect { |n| Node.hash?(n) }
      return unless association_options

      Node.value_from_hash(association_options, :class_name)
    end

    def association_name(arguments)
      return unless Node.symbol?(arguments[0])

      Node.literal_value(arguments[0])
    end
  end
end

Version data entries

3 entries across 3 versions & 1 rubygems

Version Path
packwerk-1.1.1 lib/packwerk/association_inspector.rb
packwerk-1.1.0 lib/packwerk/association_inspector.rb
packwerk-1.0.2 lib/packwerk/association_inspector.rb