Sha256: bc07f71089f65b758d2baf611cb2f9abedc7a08eabcba4792ce8d19e697082f7

Contents?: true

Size: 1.59 KB

Versions: 26

Compression:

Stored size: 1.59 KB

Contents

require 'backports/tools/alias_method_chain'

module Backports
  # Metaprogramming utility to make block optional.
  # Tests first if block is already optional when given options
  def self.make_block_optional(mod, *methods)
    mod = class << mod; self; end unless mod.is_a? Module
    options = methods.last.is_a?(Hash) ? methods.pop : {}
    methods.each do |selector|
      unless mod.method_defined? selector
        warn "#{mod}##{selector} is not defined, so block can't be made optional"
        next
      end
      unless options[:force]
        # Check if needed
        test_on = options.fetch(:test_on)
        result =  begin
                    test_on.send(selector, *options.fetch(:arg, []))
                  rescue LocalJumpError
                    false
                  end
        next if result.class.name =~ /Enumerator/
      end
      require 'enumerator'
      arity = mod.instance_method(selector).arity
      last_arg = []
      if arity < 0
        last_arg = ["*rest"]
        arity = -1-arity
      end
      arg_sequence = ((0...arity).map{|i| "arg_#{i}"} + last_arg + ["&block"]).join(", ")

      alias_method_chain(mod, selector, :optional_block) do |aliased_target, punctuation|
        mod.module_eval <<-end_eval, __FILE__, __LINE__ + 1
          def #{aliased_target}_with_optional_block#{punctuation}(#{arg_sequence})
            return to_enum(:#{aliased_target}_without_optional_block#{punctuation}, #{arg_sequence}) unless block_given?
            #{aliased_target}_without_optional_block#{punctuation}(#{arg_sequence})
          end
        end_eval
      end
    end
  end
end

Version data entries

26 entries across 26 versions & 3 rubygems

Version Path
backports-3.25.0 lib/backports/tools/make_block_optional.rb
backports-3.24.1 lib/backports/tools/make_block_optional.rb
backports-3.24.0 lib/backports/tools/make_block_optional.rb
backports-3.23.0 lib/backports/tools/make_block_optional.rb
backports-3.22.1 lib/backports/tools/make_block_optional.rb
backports-3.22.0 lib/backports/tools/make_block_optional.rb
backports-3.21.0 lib/backports/tools/make_block_optional.rb
backports-3.20.2 lib/backports/tools/make_block_optional.rb
backports-3.20.1 lib/backports/tools/make_block_optional.rb
backports-3.20.0 lib/backports/tools/make_block_optional.rb
backports-3.19.0 lib/backports/tools/make_block_optional.rb
backports-3.18.2 lib/backports/tools/make_block_optional.rb
backports-3.18.1 lib/backports/tools/make_block_optional.rb
backports-3.18.0 lib/backports/tools/make_block_optional.rb
files.com-1.0.55 docs/vendor/bundle/ruby/2.5.0/gems/backports-3.12.0/lib/backports/tools/make_block_optional.rb
backports-3.17.2 lib/backports/tools/make_block_optional.rb
backports-3.17.1 lib/backports/tools/make_block_optional.rb
backports-3.17.0 lib/backports/tools/make_block_optional.rb
backports-3.16.1 lib/backports/tools/make_block_optional.rb
backports-3.16.0 lib/backports/tools/make_block_optional.rb