nakajima-proxen 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/proxen.rb +79 -12
- metadata +1 -1
data/lib/proxen.rb
CHANGED
@@ -1,25 +1,92 @@
|
|
1
1
|
module Proxen
|
2
|
-
|
3
|
-
|
4
|
-
|
2
|
+
class Proxy
|
3
|
+
class << self
|
4
|
+
def add(klass, *args)
|
5
|
+
store[klass] = new(klass, *args)
|
6
|
+
end
|
7
|
+
|
8
|
+
def handle(instance, sym, *args, &block)
|
9
|
+
klass = Object.instance_method(:class).bind(instance).call
|
10
|
+
if proxy = store[klass]
|
11
|
+
proxy.handle(instance, sym, *args, &block)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def store
|
18
|
+
@store ||= {}
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def initialize(klass, *args)
|
23
|
+
@klass = klass
|
24
|
+
@options = args.last.is_a?(Hash) ? args.pop : {}
|
25
|
+
@targets = Array(args).flatten
|
26
|
+
|
27
|
+
blankify! if @options[:blank_slate]
|
28
|
+
end
|
29
|
+
|
30
|
+
def handle(instance, sym, *args, &block)
|
31
|
+
if target = target_for(instance, sym) and should?(instance, sym)
|
32
|
+
instance.__send__(target).__send__(sym, *args, &block)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def blankify!
|
37
|
+
@klass.class_eval do
|
5
38
|
instance_methods.each do |sym|
|
6
39
|
undef_method(sym) unless sym.to_s =~ /__/
|
7
40
|
end
|
8
41
|
end
|
9
42
|
end
|
10
|
-
|
11
|
-
|
12
|
-
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def should?(instance, sym)
|
47
|
+
case @options[:if] || @options[:unless]
|
48
|
+
when Proc then calls?(sym)
|
49
|
+
when Regexp then match?(sym)
|
50
|
+
when Symbol then sends?(instance, sym)
|
51
|
+
else true
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def calls?(sym)
|
56
|
+
case
|
57
|
+
when fn = @options[:if] then fn.call(sym)
|
58
|
+
when fn = @options[:unless] then not fn.call(sym)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def sends?(instance, sym)
|
63
|
+
case
|
64
|
+
when cond = @options[:if] then instance.__send__(cond, sym)
|
65
|
+
when cond = @options[:unless] then not instance.__send__(cond, sym)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def match?(sym)
|
70
|
+
case
|
71
|
+
when regex = @options[:if] then sym.to_s =~ regex
|
72
|
+
when regex = @options[:unless] then not sym.to_s =~ regex
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def target_for(instance, sym)
|
77
|
+
@targets.detect { |t| instance.__send__(t).respond_to?(sym) }
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def proxy_to(*targets)
|
82
|
+
Proxen::Proxy.add(self, *targets)
|
83
|
+
|
13
84
|
class_eval(<<-END, __FILE__, __LINE__)
|
14
85
|
def method_missing(sym, *args, &block)
|
15
|
-
|
16
|
-
#{target}.send(sym, *args, &block)
|
17
|
-
else
|
18
|
-
super
|
19
|
-
end
|
86
|
+
Proxen::Proxy.handle(self, sym, *args, &block) || super
|
20
87
|
end
|
21
88
|
END
|
22
89
|
end
|
23
90
|
end
|
24
91
|
|
25
|
-
Class.send :include, Proxen
|
92
|
+
Class.send :include, Proxen
|