Recently I had a project where I wanted to make a simple “centralized logger” that could be called from anywhere in a small application. I decided to set up a simple class that I could call from anywhere in the app, re-using the Ruby Logger class’s various write methods ( #debug , #warn , and so on).

I experimented with a lot of different solutions for forwarding or delegating a Ruby class method. My first stop was at the Forwardable module, but I couldn’t figure out a way to get it to delegate a class method. I eventually rigged up a somewhat hacky solution with define_method, but I wasn’t very happy with it.

Finally, a co-worker pointed me to SingleForwardable, which can be used to set up delegations for individual objects, classes, or modules. Perfect!

1 require 'logger' 2 require 'forwardable' 3 4 class SpecialLogger 5 extend SingleForwardable 6 7 @logger = Logger . new ( STDOUT ) 8 @logger . level = Logger :: INFO 9 10 def_delegators :@logger , :debug , :info , :warn , :error , :fatal 11 end 12 13 SpecialLogger . warn ( "Oh no!" ) 14 # W, [2014-12-29T15:07:39.704559 #41608] WARN -- : Oh no!

Works perfectly, and in just a few quick, extremely readable, lines of code.