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.
@@ -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