Sha256: 27dc3bee55d665b63c01802c05742a6f763c689fd438d9ae9a25b4a22b951aee

Contents?: true

Size: 1.43 KB

Versions: 1

Compression:

Stored size: 1.43 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(*as, **kw)
          handle_method = handle_method(*as, **kw)

          provider = new(*as, **kw).freeze
          frame = Frame.new(provider)

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

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

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
dry-effects-0.2.0 lib/dry/effects/provider/class_interface.rb