anchor 0.0.2 → 0.0.3
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/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
|