Take me home

before_filter-like stuff in Ruby

Written by August Lilleaas, published November 30, 2007

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!


Questions or comments?

Feel free to contact me on Twitter, @augustl, or e-mail me at august@augustl.com.