anchor 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -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 A
27
+ === Example: Using *hooks* for *models* in Rails app (Not implemented yet)
26
28
 
27
29
  Create app/hooks/model_name.rb
28
- hook to: ModelName do
30
+ anchor ModelName do
29
31
 
30
- before :save do |opts|
31
- puts opts[:method_name]
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 B
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 C
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
- extend Anchor::Hooked
50
+ include Anchor::Hooks
68
51
 
69
52
  before :save do
70
- puts "Saving #{self.inspect}"
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
@@ -1,2 +1,3 @@
1
- require 'anchor/hooked'
2
1
  require 'kernel'
2
+ require 'anchor/hooks'
3
+
@@ -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
@@ -1,9 +1,5 @@
1
1
  module Kernel
2
- def hook(opts, &block)
3
- hook_to = opts[:to]
4
- hook_to.module_eval do
5
- extend Anchor::Hooked
6
- module_eval &block
7
- end
2
+ def anchor(*objs, &block)
3
+ Anchor.hook(*objs, &block)
8
4
  end
9
5
  end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 0
8
- - 2
9
- version: 0.0.2
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-01 00:00:00 +02:00
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/hooked.rb
31
+ - lib/anchor/hooks.rb
32
32
  - lib/kernel.rb
33
33
  - lib/anchor.rb
34
34
  has_rdoc: true
@@ -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