# File lib/extlib/hook.rb, line 317
      def install_hook(type, target_method, method_sym, scope, &block)
        assert_kind_of 'target_method', target_method, Symbol
        assert_kind_of 'method_sym',    method_sym,    Symbol unless method_sym.nil?
        assert_kind_of 'scope',         scope,         Symbol

        if !block_given? and method_sym.nil?
          raise ArgumentError, "You need to pass 2 arguments to \"#{type}\"."
        end

        if method_sym.to_s[-1,1] == '='
          raise ArgumentError, "Methods ending in = cannot be hooks"
        end

        unless [ :class, :instance ].include?(scope)
          raise ArgumentError, 'You need to pass :class or :instance as scope'
        end

        if registered_as_hook?(target_method, scope)
          hooks = hooks_with_scope(scope)

          #if this hook is previously declared in a sibling or cousin we must move the :in class
          #to the common ancestor to get both hooks to run.
          if !(hooks[target_method][:in] <=> self)
            before_hook_name = hook_method_name(target_method, 'execute_before', 'hook_stack')
            after_hook_name  = hook_method_name(target_method, 'execute_after',  'hook_stack')

            hooks[target_method][:in].class_eval "remove_method :\#{before_hook_name} if instance_methods(false).any? { |m| m.to_sym == :\#{before_hook_name} }\ndef \#{before_hook_name}(*args)\nsuper\nend\n\nremove_method :\#{after_hook_name} if instance_methods(false).any? { |m| m.to_sym == :\#{before_hook_name} }\ndef \#{after_hook_name}(*args)\nsuper\nend\n", __FILE__, __LINE__ + 1

            while !(hooks[target_method][:in] <=> self) do
              hooks[target_method][:in] = hooks[target_method][:in].superclass
            end

            define_hook_stack_execution_methods(target_method, scope)
            hooks[target_method][:in].class_eval{define_advised_method(target_method, scope)}
          end
        else
          register_hook(target_method, scope)
          hooks = hooks_with_scope(scope)
        end

        #if  we were passed a block, create a method out of it.
        if block
          method_sym = "__hooks_#{type}_#{quote_method(target_method)}_#{hooks[target_method][type].length}".to_sym
          if scope == :class
            meta_class.instance_eval do
              define_method(method_sym, &block)
            end
          else
            define_method(method_sym, &block)
          end
        end

        # Adds method to the stack an redefines the hook invocation method
        hooks[target_method][type] << { :name => method_sym, :from => self }
        define_hook_stack_execution_methods(target_method, scope)
      end