Sha256: a5111a84d79daa79edeb6f0cfa479eff719e3e44e9dcb4c2d07c0dd0143ad377

Contents?: true

Size: 1.44 KB

Versions: 2

Compression:

Stored size: 1.44 KB

Contents

# frozen_string_literal: true

require 'dry/core/class_attributes'
require 'dry/effects/frame'

module Dry
  module Effects
    class Provider
      module ClassInterface
        def self.extended(base)
          base.instance_exec do
            defines :type

            @mutex = ::Mutex.new
            @effects = ::Hash.new do |es, type|
              @mutex.synchronize do
                es.fetch(type) do
                  es[type] = Class.new(Provider).tap do |provider|
                    provider.type type
                  end
                end
              end
            end
          end
        end

        include Core::ClassAttributes

        attr_reader :effects

        def [](type)
          if self < Provider
            Provider.effects.fetch(type) do
              Provider.effects[type] = ::Class.new(self).tap do |subclass|
                subclass.type type
              end
            end
          else
            @effects[type]
          end
        end

        def mixin(*args, **kwargs)
          handle_method = handle_method(*args, **kwargs)

          provider = new(*args, **kwargs).freeze
          frame = Frame.new(provider)

          ::Module.new do
            define_method(handle_method) do |*xs, &block|
              frame.(xs, &block)
            end
          end
        end

        def handle_method(*, as: Undefined, **)
          Undefined.default(as) { :"with_#{type}" }
        end
      end
    end
  end
end

Version data entries

2 entries across 2 versions & 1 rubygems

Version Path
dry-effects-0.1.1 lib/dry/effects/provider/class_interface.rb
dry-effects-0.1.0 lib/dry/effects/provider/class_interface.rb