nakajima-proxen 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|