Module: DataMapper::Hook

Public Visibility

Public Instance Method Summary

#after(target_method, method_sym = nil, &block)

Inject code that executes after the target instance method.

#after_class_method(target_method, method_sym = nil, &block)

Inject code that executes after the target class method.

#before(target_method, method_sym = nil, &block)

Inject code that executes before the target instance method.

#before_class_method(target_method, method_sym = nil, &block)

Inject code that executes before the target class method.

#define_advised_method(name, scope)

FIXME Return the method value.

#define_instance_or_class_method(new_meth_name, block, scope)
#hooks_with_scope(scope)
#inline_call(name, scope, args)
#install_hook(type, name, method_sym, scope, &block)
#method_with_scope(name, scope)

Public Instance Method Details

after

public after(target_method, method_sym = nil, &block)

Inject code that executes after the target instance method.

Meta Tags

Parameters:

target_method<Symbol>

the name of the instance method to inject after

method_sym<Symbol>

the name of the method to run after the target_method

block<Block>

the code to run after the target_method

[View source]


62
63
64
# File 'dm-core/lib/dm-core/hook.rb', line 62

def after(target_method, method_sym = nil, &block)
  install_hook :after, target_method, method_sym, :instance, &block
end

after_class_method

public after_class_method(target_method, method_sym = nil, &block)

Inject code that executes after the target class method.

Meta Tags

Parameters:

target_method<Symbol>

the name of the class method to inject after

method_sym<Symbol>

the name of the method to run after the target_method

block<Block>

the code to run after the target_method

[View source]


30
31
32
# File 'dm-core/lib/dm-core/hook.rb', line 30

def after_class_method(target_method, method_sym = nil, &block)
  install_hook :after_class_method, target_method, method_sym, :class, &block
end

before

public before(target_method, method_sym = nil, &block)

Inject code that executes before the target instance method.

Meta Tags

Parameters:

target_method<Symbol>

the name of the instance method to inject before

method_sym<Symbol>

the name of the method to run before the target_method

block<Block>

the code to run before the target_method

[View source]


46
47
48
# File 'dm-core/lib/dm-core/hook.rb', line 46

def before(target_method, method_sym = nil, &block)
  install_hook :before, target_method, method_sym, :instance, &block
end

before_class_method

public before_class_method(target_method, method_sym = nil, &block)

Inject code that executes before the target class method.

Meta Tags

Parameters:

target_method<Symbol>

the name of the class method to inject before

method_sym<Symbol>

the name of the method to run before the target_method

block<Block>

the code to run before the target_method

[View source]


15
16
17
# File 'dm-core/lib/dm-core/hook.rb', line 15

def before_class_method(target_method, method_sym = nil, &block)
  install_hook :before_class_method, target_method, method_sym, :class, &block
end

define_advised_method

public define_advised_method(name, scope)

FIXME Return the method value

[View source]


119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'dm-core/lib/dm-core/hook.rb', line 119

def define_advised_method(name, scope)
  args = args_for(hooks_with_scope(scope)[name][:old_method] ||= method_with_scope(name, scope))

  prefix = ""
  types = [:before, :after]
  if scope == :class



    prefix = "self."
    types = [:before_class_method, :after_class_method]
  elsif scope != :instance
    raise ArgumentError.new("You need to pass :class or :instance as scope")
  end

  "def \#{prefix}\#{name}(\#{args})\nretval = nil\ncatch(:halt) do\n\#{inline_hooks(name, scope, types.first, args)}\nretval = \#{inline_call(name, scope, args)}\nend\n\ncatch(:halt) do\n\#{inline_hooks(name, scope, types.last, args)}\nend\nretval\nend\n"
end

define_instance_or_class_method

public define_instance_or_class_method(new_meth_name, block, scope)
[View source]


66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'dm-core/lib/dm-core/hook.rb', line 66

def define_instance_or_class_method(new_meth_name, block, scope)
  case scope



  when :class
    class << self



      self
    end.instance_eval do
      define_method new_meth_name, block
    end
  when :instance
    define_method new_meth_name, block
  else
    raise ArgumentError.new("You need to pass :class or :instance as scope")
  end
end

hooks_with_scope

public hooks_with_scope(scope)
[View source]


81
82
83
84
85
86
87
88
89
90
91
# File 'dm-core/lib/dm-core/hook.rb', line 81

def hooks_with_scope(scope)
  case scope



  when :class then class_method_hooks
  when :instance then hooks
  else
    raise ArgumentError.new("You need to pass :class or :instance as scope")
  end
end

inline_call

public inline_call(name, scope, args)
[View source]


148
149
150
151
152
153
154
155
156
157
# File 'dm-core/lib/dm-core/hook.rb', line 148

def inline_call(name, scope, args)
      if scope == :class



if (class << superclass; self; end.method_defined?(name))
  "  super(#{args})\n"
else
  "(@__hooks_\#{scope}_\#{quote_method(name)}_old_method || @__hooks_\#{scope}_\#{quote_method(name)}_old_method =\nself.class_method_hooks[:\#{name}][:old_method]).call(\#{args})\n"
end

install_hook

public install_hook(type, name, method_sym, scope, &block)
[View source]


90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'dm-core/lib/dm-core/hook.rb', line 90

def install_hook(type, name, method_sym, scope, &block)
  raise ArgumentError.new("You need to pass 2 arguments to \"#{type}\".") if ! block_given? and method_sym.nil?
  raise ArgumentError.new("target_method should be a symbol") unless name.is_a?(Symbol)
  raise ArgumentError.new("method_sym should be a symbol") if method_sym && ! method_sym.is_a?(Symbol)
  raise ArgumentError.new("You need to pass :class or :instance as scope") unless [:class, :instance].include?(scope)

  hooks_with_scope(scope)[name][type] ||= []

  hooks_with_scope(scope)[name][type] << if block



    new_meth_name = "__hooks_#{scope}_#{type}_#{quote_method(name)}_#{hooks_with_scope(scope)[name][type].length}".to_sym
    define_instance_or_class_method(new_meth_name, block, scope)
    new_meth_name
  else
    method_sym
  end

  class_eval define_advised_method(name, scope), __FILE__, __LINE__
end

method_with_scope

public method_with_scope(name, scope)
[View source]


109
110
111
112
113
114
115
116
117
118
119
# File 'dm-core/lib/dm-core/hook.rb', line 109

def method_with_scope(name, scope)
  case scope



  when :class then method(name)
  when :instance then instance_method(name)
  else
    raise ArgumentError.new("You need to pass :class or :instance as scope")
  end
end