Sha256: 08b879490b95f6a4cbed027a0b548a3854a5ed89c1c1bd70a3d1ab966f40e266

Contents?: true

Size: 1.32 KB

Versions: 1

Compression:

Stored size: 1.32 KB

Contents

module Yaks
  # State monad-ish thing.
  #
  # Generate a DSL syntax for immutable classes.
  #
  # @example
  #
  #   # This code
  #   Control.create(:search)
  #          .method("POST")
  #          .href("/search")
  #
  #   # Can be written as
  #   StatefulBuilder.new(Control, [:method, :href]).create(:search) do
  #     method "POST"
  #     href "/search"
  #   end
  #
  class StatefulBuilder < BasicObject
    def create(*args, &block)
      @state = @klass.create(*args)
      instance_eval(&block)
      @state
    end

    def initialize(klass, methods)
      @klass = klass
      StatefulMethods.new(methods).send(:extend_object, self)
    end

    def validate_state(method_name, args)
      unless @state.instance_of?(@klass)
        ::Kernel.raise(
          IllegalState,
          "#{@klass}##{method_name}(#{args.map(&:inspect).join(', ')}) "\
          "returned #{@state.inspect}. Expected instance of #{@klass}"
        )
      end
    end

    class StatefulMethods < ::Module
      def initialize(methods)
        methods.each { |name| define_stateful_method(name) }
      end

      def define_stateful_method(method_name)
        define_method method_name do |*args, &block|
          @state = @state.public_send(method_name, *args, &block)
          validate_state(method_name, args)
        end
      end
    end
  end
end

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
yaks-0.6.0 lib/yaks/stateful_builder.rb