Tuesday, April 15, 2014

Temporarily Force a No-arg Initializer in Ruby

How to temporarily bypass a Ruby class initializer, which you shouldn't do unless you really just need access to the instance and don't require any setup that happens in the initializer:

def force_class_instance(klass)
  result = nil
  if klass.instance_method(:initialize).parameters.any? {|ar|ar[0] == :req}
    klass.class_eval 'alias_method :orig_initialize, :initialize; def initialize; end'
    result = klass.new
    warn_level = $VERBOSE
    $VERBOSE = nil
    klass.class_eval 'remove_method :initialize; alias_method :initialize, :orig_initialize; remove_method :orig_initialize'
    $VERBOSE = warn_level
  else
    result = klass.new
  end
  result
end

Now just use force_class_instance(YourClass) to get an instance.

The $VERBOSE setting is to avoid "(eval):1: warning: removing `initialize' may cause serious problems" showing up in the log.

No comments: