jdickey/repository-support

View on GitHub
lib/repository/support/test_attribute_container.rb

Summary

Maintainability
A
3 hrs
Test Coverage
# frozen_string_literal: true

# Support classes for Repository::Base and subclasses.
module Repository
  # Support classes for Repository::Base and subclasses.
  module Support
    # Adds :attributes property to caller, and enhanced attribute getter/setter.
    module TestAttributeContainer
      # rubocop:disable Metrics/AbcSize
      # rubocop:disable Metrics/CyclomaticComplexity
      # rubocop:disable Metrics/MethodLength
      def init_empty_attribute_container
        define_method :attributes do
          @attributes ||= {}
        end

        define_method(:attributes=) do |attribs|
          @attributes = attribs.to_h
        end

        define_method(:method_missing) do |method_sym, *arguments, &block|
          method_or_type = attribute_key_for?(method_sym)
          case method_or_type
          when :none
            super method_sym, arguments, block
          when :reader
            attributes[method_sym]
          else
            attributes[method_or_type] = arguments.first
          end
        end

        define_method(:respond_to?) do |method_sym, include_private = false|
          return true unless attribute_key_for?(method_sym) == :none
          super method_sym, include_private
        end

        # private
        define_method(:attribute_key_for?) do |key_sym|
          if attributes.to_h.key? key_sym
            :reader
          else
            setter_for_or_none(key_sym)
          end
        end

        # private
        define_method :setter_for_or_none do |key|
          match = key.to_s.match(/(\S+?)=/)
          has_setter = match && attributes.key?(match[1].to_sym)
          has_setter ? match[1].to_sym : :none
        end
        instance_eval { private :attribute_key_for?, :setter_for_or_none }
        self
      end # end method .init_empty_attribute_container
      # rubocop:enable Metrics/MethodLength
      # rubocop:enable Metrics/CyclomaticComplexity
      # rubocop:enable Metrics/AbcSize
      self
    end # module Repository::Support::TestAttributeContainer
  end
end