Skip to content
This repository has been archived by the owner on Jun 24, 2019. It is now read-only.

Commit

Permalink
hijacker.rb works on instance methods or class methods (doesn't affec…
Browse files Browse the repository at this point in the history
…t RoleRequirement much)

git-svn-id: http://rolerequirement.googlecode.com/svn/trunk@75 0128ec72-9f35-0410-83f6-31648bef6b25
  • Loading branch information
timcharper committed Nov 13, 2007
1 parent 565bc5a commit e691855
Showing 1 changed file with 36 additions and 18 deletions.
54 changes: 36 additions & 18 deletions lib/hijacker.rb
Expand Up @@ -17,44 +17,62 @@
class Hijacker
def initialize(klass)
@target_klass = klass
@store = []
@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?
@store << [

(@method_stores[klass]||=[]) << [
method_name,
@target_klass.instance_methods.include?(method_name) && @target_klass.instance_method(method_name)
klass.instance_methods.include?(method_name) && klass.instance_method(method_name)
]

@target_klass.send :undef_method, method_name
klass.send :undef_method, method_name
if Symbol === eval_string
@target_klass.send :define_method, method_name, @target_klass.instance_methods(eval_string)
klass.send :define_method, method_name, klass.instance_methods(eval_string)
elsif String === eval_string
@target_klass.class_eval <<-EOF
klass.class_eval <<-EOF
def #{method_name}(#{arg_names * ','})
#{eval_string}
end
EOF
elsif block_given?
@target_klass.send :define_method, method_name, block
klass.send :define_method, method_name, block
end

true
rescue
false
end

# restore all
def restore
@store.reverse_each{ |method_name, method|
@target_klass.send :undef_method, method_name
@target_klass.send :define_method, method_name, method if method
}
@store.clear
true
rescue
false
end
end

0 comments on commit e691855

Please sign in to comment.