Skip to content

Instantly share code, notes, and snippets.

@cupakromer
Created May 22, 2014 23:15
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cupakromer/fc7576dd0ff5f4fca5cb to your computer and use it in GitHub Desktop.
Save cupakromer/fc7576dd0ff5f4fca5cb to your computer and use it in GitHub Desktop.
Hack to force bool only predicates
# Original: http://media.pragprog.com/titles/ruby4/code/metaprogramming/trace_calls.rb
#
# Modified to enforce opinionated predicate responses.
# Go buy and read the book!
# Note: This is **not** thread safe.
module BoolOnlyPredicates
def self.included(klass)
klass.instance_methods(false).each do |existing_method|
wrap(klass, existing_method)
end
def klass.method_added(method) # note: nested definition
unless @force_calls_internal
@force_calls_internal = true
BoolOnlyPredicates.wrap(self, method)
@force_calls_internal = false
end
end
end
def self.wrap(klass, method)
return unless method.to_s.end_with?('?')
klass.instance_exec do
method_object = instance_method(method)
define_method(method) do |*args, &block|
!!method_object.bind(self).call(*args, &block)
end
end
end
end
Object.include BoolOnlyPredicates
# http://media.pragprog.com/titles/ruby4/code/metaprogramming/trace_calls.rb
#---
# Excerpted from "Programming Ruby 1.9 and 2.0",
# published by The Pragmatic Bookshelf.
# Copyrights apply to this code. It may not be used to create training material,
# courses, books, articles, and the like. Contact us if you are in doubt.
# We make no guarantees that this code is fit for any purpose.
# Visit http://www.pragmaticprogrammer.com/titles/ruby4 for more book information.
#---
module TraceCalls
def self.included(klass)
klass.instance_methods(false).each do |existing_method|
wrap(klass, existing_method)
end
def klass.method_added(method) # note: nested definition
unless @trace_calls_internal
@trace_calls_internal = true
TraceCalls.wrap(self, method)
@trace_calls_internal = false
end
end
end
def self.wrap(klass, method)
klass.instance_eval do
method_object = instance_method(method)
define_method(method) do |*args, &block|
puts "==> calling #{method} with #{args.inspect}"
result = method_object.bind(self).call(*args, &block)
puts "<== #{method} returned #{result.inspect}"
result
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment