anchor 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +25 -28
- data/lib/anchor.rb +2 -1
- data/lib/anchor/hooks.rb +72 -0
- data/lib/kernel.rb +2 -6
- metadata +4 -4
- data/lib/anchor/hooked.rb +0 -74
data/README.rdoc
CHANGED
@@ -5,7 +5,7 @@ Alternative for AOP libaries providing simple syntax and containing less than 10
|
|
5
5
|
Containing only:
|
6
6
|
* before
|
7
7
|
* after
|
8
|
-
* around
|
8
|
+
* around (Not implemented yet)
|
9
9
|
|
10
10
|
|
11
11
|
== Installation
|
@@ -16,61 +16,58 @@ Add to your Gemfile:
|
|
16
16
|
And run:
|
17
17
|
bundle install
|
18
18
|
|
19
|
+
Or run:
|
20
|
+
gem install anchor
|
19
21
|
|
20
22
|
|
21
23
|
== Naming recommendations
|
22
24
|
|
23
25
|
You can name things as you want, but it is recommended to it so:
|
24
26
|
|
25
|
-
=== Example
|
27
|
+
=== Example: Using *hooks* for *models* in Rails app (Not implemented yet)
|
26
28
|
|
27
29
|
Create app/hooks/model_name.rb
|
28
|
-
|
30
|
+
anchor ModelName do
|
29
31
|
|
30
|
-
before :save do
|
31
|
-
puts
|
32
|
-
puts opts[:arguments]
|
33
|
-
puts opts[:proc]
|
34
|
-
|
35
|
-
end
|
36
|
-
|
37
|
-
after :save do |opts|
|
38
|
-
puts opts[:method_name]
|
39
|
-
puts opts[:arguments]
|
40
|
-
puts opts[:proc]
|
41
|
-
puts opts[:return_value]
|
42
|
-
|
43
|
-
end
|
44
|
-
|
45
|
-
around :save do |opts|
|
46
|
-
puts opts[:method_name]
|
47
|
-
puts opts[:arguments]
|
48
|
-
puts opts[:proc]
|
49
|
-
|
50
|
-
# TODO ...
|
32
|
+
before :save do
|
33
|
+
puts "Before save #{self.inspect}"
|
51
34
|
end
|
52
35
|
|
53
36
|
end
|
54
37
|
|
55
38
|
|
56
|
-
=== Example
|
39
|
+
=== Example: Using *hooks* for *conserns* in Rails app (Not implemented yet)
|
57
40
|
|
58
41
|
Create app/hooks/model_name/what_for_hook_is_itended.rb
|
59
42
|
...
|
60
43
|
|
61
44
|
|
62
|
-
=== Example
|
45
|
+
=== Example: Using *hooks* in *models*
|
63
46
|
|
64
47
|
You can also do in app/models/your_model.rb
|
65
48
|
|
66
49
|
class YourModel
|
67
|
-
|
50
|
+
include Anchor::Hooks
|
68
51
|
|
69
52
|
before :save do
|
70
|
-
puts "
|
53
|
+
puts "Before save #{self.inspect}"
|
71
54
|
end
|
72
55
|
|
73
56
|
end
|
74
57
|
|
75
58
|
|
76
59
|
|
60
|
+
== Usage examples
|
61
|
+
|
62
|
+
=== You can find some examples from:
|
63
|
+
|
64
|
+
* https://github.com/tione/anchor/blob/master/test/test.rb
|
65
|
+
|
66
|
+
|
67
|
+
=== Method regexp
|
68
|
+
|
69
|
+
anchor Yourmodel do
|
70
|
+
before self.instance_methods.grep(/$methods/) do
|
71
|
+
puts
|
72
|
+
end
|
73
|
+
end
|
data/lib/anchor.rb
CHANGED
data/lib/anchor/hooks.rb
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
# = Anchor
|
2
|
+
module Anchor
|
3
|
+
def self.hook(*objs, &block)
|
4
|
+
objs.each do |obj|
|
5
|
+
#puts "Trying to hook: #{obj} #{block.inspect}"
|
6
|
+
Hooks.included(obj)
|
7
|
+
obj.instance_eval &block
|
8
|
+
end
|
9
|
+
end
|
10
|
+
# == Hooks
|
11
|
+
# Something similar to AOP, but much more simplified, providing: before, after, around
|
12
|
+
module Hooks
|
13
|
+
# DSL
|
14
|
+
module DSL
|
15
|
+
module Keywords
|
16
|
+
def singleton *methods; [{singleton: methods.shift}, *methods]; end
|
17
|
+
def instance *methods; [{instance: methods.shift}, *methods]; end
|
18
|
+
end
|
19
|
+
module HookTypes
|
20
|
+
def before(*methods, &block); add_hook(:before, *methods, &block); end
|
21
|
+
def after(*methods, &block); add_hook(:after, *methods, &block); end
|
22
|
+
def around(*methods, &block); add_hook(:around, *methods, &block); end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
# Hooked
|
26
|
+
module Hooked
|
27
|
+
def add_hook_for_methods(type, *methods, &block)
|
28
|
+
methods.flatten.each {|method| add_hook_for_method(type, method, &block)}
|
29
|
+
end
|
30
|
+
alias :add_hook :add_hook_for_methods
|
31
|
+
|
32
|
+
def add_hook_for_method(type, method, &block)
|
33
|
+
level, name = case method; when Hash; method.shift; when Symbol; [:instance, method]; end
|
34
|
+
# set hooks on metaclass instance, not self, if method has to be class method or self is a Object
|
35
|
+
in_scope = :metaclass if level == :singleton or not self.is_a?(Class)
|
36
|
+
return Anchor.hook(class << self; self; end) do
|
37
|
+
self.send(type, name, &block)
|
38
|
+
end if in_scope == :metaclass
|
39
|
+
# replace orginal method with hooked method
|
40
|
+
instance_exec do
|
41
|
+
hooks = @hooks ||= {}
|
42
|
+
@hooks[name] ||= {}
|
43
|
+
@hooks[name][type] ||= []
|
44
|
+
@hooks[name][type] << block
|
45
|
+
orginal_methods = @orginal_methods ||= {}
|
46
|
+
|
47
|
+
unless @orginal_methods[name]
|
48
|
+
@orginal_methods[name] = self.instance_method(name)
|
49
|
+
define_method name do
|
50
|
+
hooks[name][:before].each {|proc| proc.call} if hooks[name][:before]
|
51
|
+
retval = orginal_methods[name].bind(self).call
|
52
|
+
hooks[name][:after].each {|proc| proc.call} if hooks[name][:after]
|
53
|
+
retval
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
# Add Anchor::Hooked methods to be static
|
61
|
+
def self.included(base) # :nodoc:
|
62
|
+
base.instance_eval { extend Anchor::Hooks::ClassMethods }
|
63
|
+
end
|
64
|
+
# ClassMethods
|
65
|
+
module ClassMethods
|
66
|
+
include Anchor::Hooks::DSL::Keywords
|
67
|
+
include Anchor::Hooks::DSL::HookTypes
|
68
|
+
include Anchor::Hooks::Hooked
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
data/lib/kernel.rb
CHANGED
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
version: 0.0.
|
8
|
+
- 3
|
9
|
+
version: 0.0.3
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- "Margus P\xC3\xA4rt"
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2012-01-
|
17
|
+
date: 2012-01-03 00:00:00 +02:00
|
18
18
|
default_executable:
|
19
19
|
dependencies: []
|
20
20
|
|
@@ -28,7 +28,7 @@ extra_rdoc_files: []
|
|
28
28
|
|
29
29
|
files:
|
30
30
|
- README.rdoc
|
31
|
-
- lib/anchor/
|
31
|
+
- lib/anchor/hooks.rb
|
32
32
|
- lib/kernel.rb
|
33
33
|
- lib/anchor.rb
|
34
34
|
has_rdoc: true
|
data/lib/anchor/hooked.rb
DELETED
@@ -1,74 +0,0 @@
|
|
1
|
-
|
2
|
-
module Anchor
|
3
|
-
# Something similar to AOP, but much more simplified, providing:
|
4
|
-
# * before
|
5
|
-
# * after
|
6
|
-
# * around
|
7
|
-
module Hooked
|
8
|
-
# Information about hooks is stored in @hooks
|
9
|
-
attr_reader :hooks
|
10
|
-
# Orginal methods are not aliased but stored in @orginal_methods as UnboundMethod
|
11
|
-
attr_reader :orginal_methods
|
12
|
-
|
13
|
-
def before(*methods, &block)
|
14
|
-
create_hook(:before, *methods, &block)
|
15
|
-
end
|
16
|
-
|
17
|
-
def after(*methods, &block)
|
18
|
-
create_hook(:after, *methods, &block)
|
19
|
-
end
|
20
|
-
|
21
|
-
def around(*methods, &block)
|
22
|
-
create_hook(:around, *methods, &block)
|
23
|
-
end
|
24
|
-
|
25
|
-
def create_hook(type, *methods, &block)
|
26
|
-
@hooks ||= {}
|
27
|
-
@orginal_methods ||= {}
|
28
|
-
|
29
|
-
methods.each do |method|
|
30
|
-
method_scope = :instance
|
31
|
-
method_name = case method; when Hash; method_scope, name = method.flatten; name; when Symbol; method; end
|
32
|
-
|
33
|
-
# if hook on static, call new hook on self metaclass
|
34
|
-
return hook({to: class << self; self; end}, &block) if method_scope == :static
|
35
|
-
|
36
|
-
# register hook
|
37
|
-
@hooks[method_name] ||= {}
|
38
|
-
@hooks[method_name][type] ||= []
|
39
|
-
@hooks[method_name][type] << block
|
40
|
-
|
41
|
-
# store and replace orginal method
|
42
|
-
unless @orginal_methods[method_name]
|
43
|
-
# store orginal
|
44
|
-
@orginal_methods[method_name] = self.instance_method(method_name)
|
45
|
-
|
46
|
-
# replace orginal to call hooks and orginal
|
47
|
-
define_method method_name do
|
48
|
-
hooks = self.class.methods.include?(:hooks) ? self.class.hooks : class << self; self.hooks; end
|
49
|
-
orginal_methods = self.class.methods.include?(:orginal_methods) ? self.class.orginal_methods : class << self; self.orginal_methods; end
|
50
|
-
# Hooks. Before.
|
51
|
-
before_hooks = hooks[method_name][:before]
|
52
|
-
before_hooks.each do |proc|
|
53
|
-
proc.call
|
54
|
-
end if before_hooks
|
55
|
-
# bind method to self and call
|
56
|
-
retval = orginal_methods[method_name].bind(self).call
|
57
|
-
# Hooks. After.
|
58
|
-
after_hooks = hooks[method_name][:after]
|
59
|
-
after_hooks.each do |proc|
|
60
|
-
proc.call
|
61
|
-
end if after_hooks
|
62
|
-
# return value returned by orginal method
|
63
|
-
retval
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
|
68
|
-
end
|
69
|
-
end
|
70
|
-
protected :create_hook
|
71
|
-
|
72
|
-
end
|
73
|
-
|
74
|
-
end
|