crochet 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.
- data/lib/crochet.rb +73 -0
- metadata +46 -0
data/lib/crochet.rb
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
module Crochet
|
2
|
+
VERSION = "0.0.1"
|
3
|
+
class Hook
|
4
|
+
# Map symbols to their class- or instance-relevant methods
|
5
|
+
TYPE_SPECS = {
|
6
|
+
:instance => {
|
7
|
+
:accessor => :instance_method,
|
8
|
+
:definer => :define_method,
|
9
|
+
:evaluator => :instance_exec
|
10
|
+
},
|
11
|
+
:class => {
|
12
|
+
:accessor => :method,
|
13
|
+
:definer => :define_singleton_method,
|
14
|
+
:evaluator => :class_exec
|
15
|
+
}
|
16
|
+
}
|
17
|
+
def initialize(klass, &block)
|
18
|
+
@klass = klass
|
19
|
+
@methods = []
|
20
|
+
self.instance_eval(&block) if block
|
21
|
+
end
|
22
|
+
def _attach(timing, destructive, method, method_type=:instance, &block)
|
23
|
+
specs = TYPE_SPECS[method_type]
|
24
|
+
|
25
|
+
# Capture the original method
|
26
|
+
orig_method = @klass.method(specs[:accessor]).(method)
|
27
|
+
|
28
|
+
# Redefine the method
|
29
|
+
@klass.send(specs[:definer], method) do |*args|
|
30
|
+
# Pass the original arguments "before" hook methods
|
31
|
+
if timing == :before
|
32
|
+
hook_result = self.send(specs[:evaluator], *args, &block)
|
33
|
+
args = hook_result if destructive
|
34
|
+
end
|
35
|
+
|
36
|
+
# Call the original method and assign the result
|
37
|
+
method_result = (method_type == :instance ? orig_method.bind(self) : orig_method).call(*args)
|
38
|
+
|
39
|
+
# Pass method result, followed by the args it received, to "after" hook methods
|
40
|
+
if timing == :after
|
41
|
+
hook_result = self.send(specs[:evaluator], method_result, *args, &block)
|
42
|
+
method_result = hook_result if destructive
|
43
|
+
end
|
44
|
+
|
45
|
+
# Finally, return the (optionally overridden) method result
|
46
|
+
method_result
|
47
|
+
end
|
48
|
+
@methods << { :orig => orig_method, :name => method, :type => method_type }
|
49
|
+
nil
|
50
|
+
end
|
51
|
+
|
52
|
+
# Define hook methods and their destructive twins
|
53
|
+
[ :before, :after, :before!, :after! ].each do |method|
|
54
|
+
define_method method do |*args, &block|
|
55
|
+
str = method.to_s
|
56
|
+
destructive = (str[-1] == "!")
|
57
|
+
timing = (destructive ? str[0...-1].to_sym : method)
|
58
|
+
_attach(timing, destructive, *args, &block)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# When `destroy` is called, it should restore all affected methods
|
63
|
+
def destroy
|
64
|
+
@methods.each do |method|
|
65
|
+
specs = TYPE_SPECS[method[:type]]
|
66
|
+
@klass.send(specs[:definer], method[:name]) do |*args|
|
67
|
+
(method[:type] == :instance ? method[:orig].bind(self) : method[:orig]).call(*args)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
@methods = []
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
metadata
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: crochet
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Jeremy Singer-Vine
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-05-05 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: Hook into and/or monkeypatch any Ruby class- or instance-method. Provides
|
15
|
+
'before' and 'after' hooks, plus their destructive evil twins.
|
16
|
+
email: jsvine@gmail.com
|
17
|
+
executables: []
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- lib/crochet.rb
|
22
|
+
homepage: https://github.com/jsvine/crochet
|
23
|
+
licenses: []
|
24
|
+
post_install_message:
|
25
|
+
rdoc_options: []
|
26
|
+
require_paths:
|
27
|
+
- lib
|
28
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
29
|
+
none: false
|
30
|
+
requirements:
|
31
|
+
- - ! '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
35
|
+
none: false
|
36
|
+
requirements:
|
37
|
+
- - ! '>='
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0'
|
40
|
+
requirements: []
|
41
|
+
rubyforge_project:
|
42
|
+
rubygems_version: 1.8.23
|
43
|
+
signing_key:
|
44
|
+
specification_version: 3
|
45
|
+
summary: Simple Ruby hooks.
|
46
|
+
test_files: []
|