lib/hijacker.rb
# Hijacker class
#
# This class is used by RoleRequirementTestHelper to temporarily hijack a controller action for testing
#
# It can be used for other tests as well.
#
# You can contract the author with questions
# Tim C. Harper - irb(main):001:0> ( 'tim_see_harperATgmail._see_om'.gsub('_see_', 'c').gsub('AT', '@') )
#
#
# Example usage:
# hijacker = Hijacker.new(ListingsController)
# hijacker.hijack_instance_method("index", "render :text => 'hello world!'" )
# get :index # will return "hello world"
# hijacker.restore # put things back the way you found it
class Hijacker
def initialize(klass)
@target_klass = klass
@method_stores = {}
end
def hijack_class_method(method_name, eval_string = nil, arg_names = [], &block)
hijack_method(class_self_instance, method_name, eval_string, arg_names, &block )
end
def hijack_instance_method(method_name, eval_string = nil, arg_names = [], &block)
hijack_method(@target_klass, method_name, eval_string, arg_names, &block )
end
# restore all
def restore
@method_stores.each_pair{|klass, method_stores|
method_stores.reverse_each{ |method_name, method|
klass.send :undef_method, method_name
klass.send :define_method, method_name, method if method
}
}
@method_stores.clear
true
rescue
false
end
protected
def class_self_instance
@target_klass.send :eval, "class << self; self; end;"
end
def hijack_method(klass, method_name, eval_string = nil, arg_names = [], &block)
method_name = method_name.to_s
# You have got love ruby! What other language allows you to pillage and plunder a class like this?
(@method_stores[klass]||=[]) << [
method_name,
klass.instance_methods.include?(method_name) && klass.instance_method(method_name)
]
klass.send :undef_method, method_name
if Symbol === eval_string
klass.send :define_method, method_name, klass.instance_methods(eval_string)
elsif String === eval_string
klass.class_eval <<-EOF
def #{method_name}(#{arg_names * ','})
#{eval_string}
end
EOF
elsif block_given?
klass.send :define_method, method_name, block
end
true
rescue
false
end
end