zeisler/active_mocker

View on GitHub
lib/active_mocker/mock_creator/safe_methods.rb

Summary

Maintainability
A
0 mins
Test Coverage
# frozen_string_literal: true
module ActiveMocker
  class MockCreator
    module SafeMethods
      BASE = { instance_methods: [], scopes: [], methods: [], all_methods_safe: false }.freeze

      def safe_method?(type, name)
        plural_type      = (type.to_s + "s").to_sym
        all_methods_safe = all_methods_safe?(type, name)
        return true if all_methods_safe
        return true if safe_methods[plural_type].include?(name)
        false
      end

      private

      def safe_methods
        @safe_methods ||= class_introspector.parsed_source.comments.each_with_object(BASE.dup) do |comment, hash|
          if comment.text.include?("ActiveMocker.all_methods_safe")
            hash[:all_methods_safe] = ActiveMocker.module_eval(comment.text.delete("#"))
          elsif comment.text.include?("ActiveMocker.safe_methods")
            hash.merge!(ActiveMocker.module_eval(comment.text.delete("#")))
          else
            hash
          end
        end
      end

      def all_methods_safe?(type, name)
        plural_type      = (type.to_s + "s").to_sym
        all_methods_safe = safe_methods.fetch(:all_methods_safe)
        if all_methods_safe.is_a?(Hash)
          !all_methods_safe.fetch(plural_type).include?(name)
        else
          all_methods_safe
        end
      end

      module ActiveMocker
        class << self
          def safe_methods(*arg_methods, scopes: [], instance_methods: [], class_methods: [], all_methods_safe: false)
            {
              instance_methods: arg_methods.concat(instance_methods),
              scopes:           scopes,
              methods:          class_methods,
              all_methods_safe: all_methods_safe,
            }
          end

          def all_methods_safe(except: {})
            other_keys = except.except(:instance_methods, :scopes, :class_methods)
            unless other_keys.empty?
              raise ArgumentError, "ActiveMocker.all_methods_safe arguments must only be `except: { instance_methods: [], scopes: [], class_methods: [] }`"
            end
            {
              instance_methods: except.fetch(:instance_methods, []),
              scopes:           except.fetch(:scopes, []),
              methods:          except.fetch(:class_methods, []),
            }
          end
        end
      end
    end
  end
end