stub_a 0.0.1
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.
- checksums.yaml +7 -0
- data/lib/stub_a.rb +154 -0
- metadata +44 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: 022265f955db24a8dd7a3bb3465243121379ecd8
|
|
4
|
+
data.tar.gz: 86be306baf3ec972fdf4163e7ced3920e7bc4407
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: aaff64bee34e4ce474b09fe009188c83af14b39128cd44bbaddc55d8055e4e71a7aeb789d097ae45acc8d685f0890571e8603da53178a7223c4a19a0a1a5c639
|
|
7
|
+
data.tar.gz: d156071d484adaf0b2be902a1eb7903c33c9b9d2fd0271371e4b472aca42387d2a3b5120703c3256da55ba17357fbd64b0c80ea0bc402a77f5af9023fcadc4ea
|
data/lib/stub_a.rb
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
class StubA
|
|
2
|
+
def initialize(object)
|
|
3
|
+
@target_class = object if object.is_a? Class
|
|
4
|
+
@target_class ||= class << object; self; end
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
[:before,
|
|
8
|
+
:after,
|
|
9
|
+
].each do |hook_type|
|
|
10
|
+
define_method hook_type, ->(method, &block) {
|
|
11
|
+
make_hook_points(method)
|
|
12
|
+
|
|
13
|
+
method_name = hook_method_name(method, hook_type)
|
|
14
|
+
hook = block if block
|
|
15
|
+
hook ||= default_hook(method, hook_type)
|
|
16
|
+
@target_class.__send__ :define_method, method_name, hook
|
|
17
|
+
self
|
|
18
|
+
}
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def stub(method, &block)
|
|
22
|
+
raise ArgumentError, "No block" unless block
|
|
23
|
+
make_hook_points(method)
|
|
24
|
+
|
|
25
|
+
method_name = hook_method_name(method, :stub)
|
|
26
|
+
@target_class.__send__ :define_method, method_name, block
|
|
27
|
+
self
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def restore(method=nil, *types)
|
|
31
|
+
if method.nil?
|
|
32
|
+
hooks = defined_hooks
|
|
33
|
+
method = hooks.keys.first if hooks.keys.size == 1
|
|
34
|
+
end
|
|
35
|
+
raise "Method name to be restored is required." if method.nil?
|
|
36
|
+
|
|
37
|
+
available_types = METHOD_TYPES - [:origin]
|
|
38
|
+
raise "Type error" if (types - available_types).size > 0
|
|
39
|
+
types = available_types if types.empty?
|
|
40
|
+
types.uniq!
|
|
41
|
+
|
|
42
|
+
types.each do |type|
|
|
43
|
+
method_name = hook_method_name(method, type)
|
|
44
|
+
next unless @target_class.method_defined? method_name
|
|
45
|
+
@target_class.__send__ :remove_method, method_name
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
hooks = defined_hooks
|
|
49
|
+
if hooks[method.to_s].size == 1 and
|
|
50
|
+
hooks[method.to_s].first == 'origin'
|
|
51
|
+
origin = hook_method_name(method, :origin)
|
|
52
|
+
@target_class.__send__ :alias_method, method, origin
|
|
53
|
+
@target_class.__send__ :remove_method, origin
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def restore_all
|
|
58
|
+
defined_hooks.each do |method, types|
|
|
59
|
+
types.each do |type|
|
|
60
|
+
name = hook_method_name(method, type)
|
|
61
|
+
next unless @target_class.method_defined? name
|
|
62
|
+
@target_class.__send__ :alias_method, method, name if type == 'origin'
|
|
63
|
+
@target_class.__send__ :remove_method, name
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
private
|
|
69
|
+
METHOD_TYPES = [
|
|
70
|
+
:before,
|
|
71
|
+
:after,
|
|
72
|
+
:stub,
|
|
73
|
+
:origin,
|
|
74
|
+
]
|
|
75
|
+
private_constant :METHOD_TYPES
|
|
76
|
+
|
|
77
|
+
def hook_method_name(method, type)
|
|
78
|
+
"===>(stub_a) #{type}-#{method}"
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def hook_method_names(method)
|
|
82
|
+
METHOD_TYPES.each_with_object({}) do |t, h|
|
|
83
|
+
h[t] = hook_method_name(method, t)
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def make_hook_points(method_name)
|
|
88
|
+
methods = hook_method_names(method_name)
|
|
89
|
+
return if @target_class.method_defined? methods[:origin]
|
|
90
|
+
|
|
91
|
+
@target_class.__send__ :alias_method, methods[:origin], method_name
|
|
92
|
+
@target_class.__send__ :define_method, method_name, ->(*args, &block) {
|
|
93
|
+
if respond_to? methods[:before]
|
|
94
|
+
__send__ methods[:before], ARGS[:before].new(method_name, args), &block
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
if respond_to? methods[:stub]
|
|
98
|
+
origin = __send__ :method, methods[:origin]
|
|
99
|
+
val = __send__ methods[:stub], ARGS[:stub].new(origin, args), &block
|
|
100
|
+
else
|
|
101
|
+
val = __send__ methods[:origin], *args, &block
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
if respond_to? methods[:after]
|
|
105
|
+
__send__ methods[:after], ARGS[:after].new(method_name, val)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
val
|
|
109
|
+
}
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def defined_hooks
|
|
113
|
+
re = /\A===>\(stub_a\) (before|after|stub|origin)-(.+)\z/
|
|
114
|
+
@target_class.instance_methods.each_with_object({}) {|name, h|
|
|
115
|
+
if name.to_s =~ re
|
|
116
|
+
h[$2] ||= []
|
|
117
|
+
h[$2] << $1
|
|
118
|
+
end
|
|
119
|
+
}
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def default_hook(method, type)
|
|
123
|
+
case type.to_sym
|
|
124
|
+
when :before
|
|
125
|
+
default_before_hook(method)
|
|
126
|
+
when :after
|
|
127
|
+
default_after_hook(method)
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def default_before_hook(method)
|
|
132
|
+
->(method, *args, &block) {
|
|
133
|
+
puts "[#{Time.now}] call `#{method}' (#{self.inspect})"
|
|
134
|
+
puts "args: #{args.inspect}" if args.size > 0
|
|
135
|
+
}
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def default_after_hook(method)
|
|
139
|
+
before_method = hook_method_name(method, :before)
|
|
140
|
+
->(method, val) {
|
|
141
|
+
unless respond_to? before_method
|
|
142
|
+
puts "[#{Time.now}] call `#{method}' (#{self.inspect})"
|
|
143
|
+
end
|
|
144
|
+
puts "return: #{val.inspect}"
|
|
145
|
+
}
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
ARGS = {
|
|
149
|
+
before: Struct.new(:method_name, :args),
|
|
150
|
+
stub: Struct.new(:method, :args),
|
|
151
|
+
after: Struct.new(:method_name, :return_value),
|
|
152
|
+
}
|
|
153
|
+
private_constant :ARGS
|
|
154
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: stub_a
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.1
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- 60ml
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2015-02-07 00:00:00.000000000 Z
|
|
12
|
+
dependencies: []
|
|
13
|
+
description: a tool to manipulate objects with hooks and stubs
|
|
14
|
+
email: bd.4975.3110@gmail.com
|
|
15
|
+
executables: []
|
|
16
|
+
extensions: []
|
|
17
|
+
extra_rdoc_files: []
|
|
18
|
+
files:
|
|
19
|
+
- lib/stub_a.rb
|
|
20
|
+
homepage: https://github.com/60ml/stub_a
|
|
21
|
+
licenses:
|
|
22
|
+
- MIT
|
|
23
|
+
metadata: {}
|
|
24
|
+
post_install_message:
|
|
25
|
+
rdoc_options: []
|
|
26
|
+
require_paths:
|
|
27
|
+
- lib
|
|
28
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - ">="
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '0'
|
|
33
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
34
|
+
requirements:
|
|
35
|
+
- - ">="
|
|
36
|
+
- !ruby/object:Gem::Version
|
|
37
|
+
version: '0'
|
|
38
|
+
requirements: []
|
|
39
|
+
rubyforge_project:
|
|
40
|
+
rubygems_version: 2.4.5
|
|
41
|
+
signing_key:
|
|
42
|
+
specification_version: 4
|
|
43
|
+
summary: a tool to manipulate objects with hooks and stubs
|
|
44
|
+
test_files: []
|