Skip to content

Instantly share code, notes, and snippets.

@sdeming
Created January 29, 2012 01:48
Show Gist options
  • Save sdeming/1696658 to your computer and use it in GitHub Desktop.
Save sdeming/1696658 to your computer and use it in GitHub Desktop.
predicate method chaining
module PredicateMethods
module Firewalls
class Allow
def initialize(what)
@wrappee = what
end
def method_missing(name, *args, &blk)
begin
@wrappee.send(name, *args, &blk)
rescue NoMethodError
eval "#{name} *args, &blk"
end
end
end
class Deny
def method_missing name, *args, &blk
self
end
end
end
def define_predicate name, predicate
name = name.to_s.sub(/\?$/, '')
p, m = :"#{name}?", :"#{name}"
send(:define_method, p) do |*args, &blk|
predicate.call(*args)
end
send(:define_method, m) do |*args, &blk|
if send(p, *args)
if blk
blk.call
else
@_predwrapper ||= Firewalls::Allow.new(self)
end
else
Firewalls::Deny.new
end
end
end
end
class T
extend PredicateMethods
define_predicate :yep, lambda { true }
define_predicate :nope, lambda { false }
define_predicate :maybe, lambda { |eh| eh }
end
x = T.new
x.yep.puts "x:Yep"
x.yep.yep.yep.yep { puts "x:Yeeeeep" }
x.nope.nope.nope.nope { puts "x:Nooooope" }
x.nope.puts "x:Nope"
x.yep.nope.puts "x:Nuh uh"
x.puts "x:I should raise NoMethodError" rescue nil
y = T.new
y.nope.puts "y:Nope"
y.puts "y:I should raise NoMethodError" rescue nil
y.maybe(true).puts "y:Maybe"
y.yep.maybe(true).yep.puts "y:Yep-Maybe-Yep"
y.maybe(false).puts "y:Maybe not"
@sdeming
Copy link
Author

sdeming commented Jan 29, 2012

Scott, don't end your sentences in prepositions. It clearly breaks reading comprehensibility then. Oops.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment