Doin’ some phat Ruby to add Rails’ before_filter
-like behavior in Ruby (outside of Rails)
If you ever wanted Rails’ neat before_filter
kind of stuff outside of Rails, here’s how do to just that.
We’re creating a proxy class, that uses method_missing
to do some magic. Whenever we call a method on this proxy class, the before filter stuff is called, and then the actual method we call. This proxy class also has all methods removed from it (such as inspect
, new
, methods
and so on.
The actual method that we’re calling, however, is called on another class. This is done so that we can indeed do the filters on internal methods like send
etc, as mentioned above.
class Cool
def be_cool
puts "I'm so damn cool tbh"
end
end
class Silly
instance_methods.each do |meth|
undef_method(meth) unless meth =~ /\A__/
end
def initialize
@delegate = Cool.new
@plz_do = []
end
def method_missing(meth, *args, &block)
@plz_do.each {|action| action.call }
@delegate.send(meth, *args, &block)
end
def plz_do(this = nil, &block)
if block_given?
@plz_do << block
elsif this.respond_to?(:call)
@plz_do << this
elsif this.respond_to?(:to_str)
@plz_do << proc { eval(this) }
end
end
end
The undef_method
stuff is the magic thingie that undefines all the built-in methods we automatically inherit from <span class="co">Object</span>
and <span class="co">Kernel</span>
.
Usage:
s = Silly.new
s.plz_do proc { puts "Hello, there" }
s.plz_do "puts 'Oh yeah!'"
s.plz_do { puts "BUT OMG!" }
s.be_cool
# Hello, there
# Oh yeah!
# BUT OMG!
# I'm so damn cool tbh
We use plz_do
to add stuff to the filter. All the items are stored in procs, inside an array. Those items are looped through and called before the be_cool
method is called.
Hawt!