lab42_aop 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 26ab30b83d3cd0b4ee26f54c8357e4f12483bf79
4
+ data.tar.gz: ab75d29b075a3d694914046ac47fff0c38d24526
5
+ SHA512:
6
+ metadata.gz: 0eccaa990ce26738605b05d6cfdbb8f0a5386b9c248807da9e07bc1ece2d999d55fd7a84544de08466564355ada03acc069c14e1034c07f2d6b7e6d6b03636b2
7
+ data.tar.gz: eeebc7bf7ccf0df1f0e9ae4b000e09167d7cb698594dd8a2cb2074d856bb95e2e53155c684a519a65b0dc02fdb17a4cdd80acbd1f3ae2afb64d681fe109d6fef
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 Robert Dober
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,9 @@
1
+ # Lab42 Programmer's Best Friend In Ruby2
2
+
3
+ ## AOP
4
+
5
+ Aspect Oriented Programming
6
+
7
+
8
+ Please see the [QED](http://rubyworks.github.io/qed/) demos [here](https://github.com/RobertDober/lab42_aop/blob/master/demo)
9
+ for details.
@@ -0,0 +1,41 @@
1
+ module Lab42
2
+ module AOP
3
+ module After extend self
4
+ def with_block rcv, tgts, **kwds, &blk
5
+ concerns = CrossConcern.get_methods rcv, Array( tgts ), **kwds
6
+ concerns.each do | tgt_concern |
7
+ _define_block_after tgt_concern, blk
8
+ end
9
+ end
10
+
11
+ def with_methods rcv, tgts, aops, **kwds
12
+ Array( aops ).each do | aop |
13
+ concerns = CrossConcern.get_methods rcv, Array( tgts ), **kwds
14
+ concerns.each do | tgt_concern |
15
+ _define_method_after tgt_concern, aop
16
+ end
17
+ end
18
+ end
19
+
20
+ private
21
+ def _define_block_after tgt_concern, blk
22
+ unique_name = "__#{tgt_concern.name}_#{SecureRandom.uuid.gsub('-','_')}"
23
+ tgt_concern.cls.send :define_method, unique_name, &blk
24
+ tgt_concern.cls.send :define_method, tgt_concern.name do |*a, &b|
25
+ tgt_concern.mthd.bind( self ).( *a, &b ).tap do
26
+ send unique_name, *a, &b
27
+ end
28
+ end
29
+
30
+ end
31
+
32
+ def _define_method_after tgt_concern, aop
33
+ tgt_concern.cls.send :define_method, tgt_concern.name do |*a, &b|
34
+ tgt_concern.mthd.bind( self ).( *a, &b ).tap do
35
+ send( aop, *a, &b )
36
+ end
37
+ end
38
+ end
39
+ end # module After
40
+ end # module AOP
41
+ end # module Lab42
@@ -0,0 +1,42 @@
1
+ module Lab42
2
+ module AOP
3
+ module Around extend self
4
+ def with_block rcv, tgts, **kwds, &blk
5
+ concerns = CrossConcern.get_methods rcv, Array( tgts ), **kwds
6
+ concerns.each do | tgt_concern |
7
+ _define_block_around tgt_concern, blk
8
+ end
9
+ end
10
+
11
+ def with_methods rcv, tgts, aops, **kwds
12
+ Array( aops ).each do | aop |
13
+ concerns = CrossConcern.get_methods rcv, Array( tgts ), **kwds
14
+ concerns.each do | tgt_concern |
15
+ _define_method_around tgt_concern, aop
16
+ end
17
+ end
18
+ end
19
+
20
+ private
21
+ def _define_block_around tgt_concern, blk
22
+ unique_name = "__#{tgt_concern.name}_#{SecureRandom.uuid.gsub('-','_')}"
23
+ tgt_concern.cls.send :define_method, unique_name, &blk
24
+ tgt_concern.cls.send :define_method, tgt_concern.name do |*a, &b|
25
+ result_wrapper = Tools.mk_result_wrapper tgt_concern.mthd.bind( self ), tgt_concern.name
26
+ send unique_name, result_wrapper, *a, &b
27
+ result_wrapper.result
28
+ end
29
+ end
30
+
31
+ def _define_method_around tgt_concern, aop
32
+ result = nil
33
+ tgt_concern.cls.send :define_method, tgt_concern.name do |*a, &b|
34
+ result_wrapper = Tools.mk_result_wrapper tgt_concern.mthd.bind( self ), tgt_concern.name
35
+ send aop, result_wrapper, *a, &b
36
+ result_wrapper.result
37
+ end
38
+ end
39
+
40
+ end # module Around
41
+ end # module AOP
42
+ end # module Lab42
@@ -0,0 +1,3 @@
1
+ require_relative '../aop'
2
+
3
+ AOP = Lab42::AOP
@@ -0,0 +1,41 @@
1
+ module Lab42
2
+ module AOP
3
+ module Before extend self
4
+ def with_block rcv, tgts, **kwds, &blk
5
+ concerns = CrossConcern.get_methods rcv, Array( tgts ), **kwds
6
+ concerns.each do | tgt_concern |
7
+ _define_block_before tgt_concern, blk
8
+ end
9
+ end
10
+
11
+ def with_methods rcv, tgts, aops, **kwds
12
+ # aops loop must be outer loop as _define_method_before will change
13
+ # the result of CrossConcern.get_methods rcv, ...
14
+ Array( aops ).each do | aop |
15
+ concerns = CrossConcern.get_methods rcv, Array( tgts ), **kwds
16
+ concerns.each do | tgt_concern |
17
+ _define_method_before tgt_concern, aop
18
+ end
19
+ end
20
+ end
21
+
22
+ private
23
+ def _define_block_before tgt_concern, blk
24
+ unique_name = "__#{tgt_concern.name}_#{SecureRandom.uuid.gsub('-','_')}"
25
+ tgt_concern.cls.send :define_method, unique_name, &blk
26
+ tgt_concern.cls.send :define_method, tgt_concern.name do |*a, &b|
27
+ send unique_name, *a, &b
28
+ tgt_concern.mthd.bind( self ).( *a, &b )
29
+ end
30
+
31
+ end
32
+
33
+ def _define_method_before tgt_concern, aop
34
+ tgt_concern.cls.send :define_method, tgt_concern.name do |*a, &b|
35
+ send( aop, *a, &b )
36
+ tgt_concern.mthd.bind( self ).( *a, &b )
37
+ end
38
+ end
39
+ end # module Before
40
+ end # module AOP
41
+ end # module Lab42
@@ -0,0 +1,8 @@
1
+ # module Lab42
2
+ # module AOP extend self
3
+ # module ConcernScope
4
+ # def concern_scope &blk
5
+ # end
6
+ # end # module ConcernScope
7
+ # end
8
+ # end # module Lab42
@@ -0,0 +1,60 @@
1
+ require 'ostruct'
2
+
3
+ module Lab42
4
+ module AOP extend self
5
+ module CrossConcern extend self
6
+ def get_methods cls, mthd_specs, **kwds
7
+ mthd_specs
8
+ .map{ |ms| _get_methods cls, ms, **kwds }
9
+ .flatten
10
+ .compact
11
+ .uniq
12
+ end
13
+
14
+ private
15
+ def _exclude_candidates candidates, exclude
16
+ case exclude
17
+ when Array
18
+ candidates - exclude
19
+ when Symbol
20
+ candidates - Array( exclude )
21
+ when Regexp
22
+ candidates - candidates.grep( exclude )
23
+ end
24
+ end
25
+ def _get_methods cls, mthd_spec, include_included: false, exclude: nil
26
+ candidates = _get_methods_candidates cls, mthd_spec, include_included: include_included
27
+ candidates = _exclude_candidates( candidates, exclude ) if exclude
28
+ _make_concerns( cls, candidates )
29
+ end
30
+
31
+ def _get_methods_candidates cls, mthd_spec, include_included: false
32
+ case mthd_spec
33
+ when Symbol
34
+ [ mthd_spec ]
35
+ when String
36
+ cls
37
+ .instance_methods( include_included )
38
+ .grep( %r{#{mthd_spec}} )
39
+ when Regexp
40
+ cls
41
+ .instance_methods( include_included )
42
+ .grep( mthd_spec )
43
+ when Module
44
+ mthd_spec
45
+ .instance_methods( include_included )
46
+ end
47
+ end
48
+
49
+ def _make_concerns cls, mss
50
+ mss.map{ |ms| _make_concern cls, ms }
51
+ end
52
+ def _make_concern cls, mthd_spec
53
+ OpenStruct.new cls: cls, name: mthd_spec, mthd: cls.instance_method( mthd_spec )
54
+ rescue
55
+ nil
56
+ end
57
+
58
+ end # module CrossConcern
59
+ end # module AOP
60
+ end # module Lab42
@@ -0,0 +1,19 @@
1
+ module Lab42
2
+ module AOP extend self
3
+ module Meta extend self
4
+ def add_singleton_method objct, name, &method
5
+ class << objct; self end.module_eval do
6
+ define_method name, &method
7
+ end
8
+ objct
9
+ end
10
+
11
+ def add_attribute objct, att_name
12
+ class << objct; self end.module_eval do
13
+ attr_accessor att_name
14
+ end
15
+ objct
16
+ end
17
+ end # module Meta
18
+ end # module AOP
19
+ end # module Lab42
@@ -0,0 +1,36 @@
1
+ module Lab42
2
+ module AOP
3
+ module ParamFilter extend self
4
+ def with_block rcv, tgts, **kwds, &blk
5
+ concerns = CrossConcern.get_methods rcv, Array( tgts ), **kwds
6
+ concerns.each do | tgt_concern |
7
+ _define_block_param_filter tgt_concern, blk
8
+ end
9
+ end
10
+
11
+ def with_methods rcv, tgts, aops, **kwds
12
+ Array( aops ).each do | aop |
13
+ concerns = CrossConcern.get_methods rcv, Array( tgts ), **kwds
14
+ concerns.each do | tgt_concern |
15
+ _define_method_param_filter tgt_concern, aop
16
+ end
17
+ end
18
+ end
19
+
20
+ private
21
+ def _define_block_param_filter tgt_concern, blk
22
+ tgt_concern.cls.send :define_method, tgt_concern.name do |*a, &b|
23
+ new_params = blk.(*a)
24
+ tgt_concern.mthd.bind( self ).( *new_params, &b )
25
+ end
26
+ end
27
+
28
+ def _define_method_param_filter tgt_concern, aop
29
+ tgt_concern.cls.send :define_method, tgt_concern.name do |*a, &b|
30
+ new_params = send( aop, *a )
31
+ tgt_concern.mthd.bind( self ).( *new_params, &b )
32
+ end
33
+ end
34
+ end # module ParamFilter
35
+ end # module AOP
36
+ end # module Lab42
@@ -0,0 +1,40 @@
1
+ module Lab42
2
+ module AOP
3
+ module ResultFilter extend self
4
+ def with_block rcv, tgts, **kwds, &blk
5
+ concerns = CrossConcern.get_methods rcv, Array( tgts ), **kwds
6
+ concerns.each do | tgt_concern |
7
+ _define_block_result_filter tgt_concern, blk
8
+ end
9
+ end
10
+
11
+ def with_methods rcv, tgts, aops, **kwds
12
+ Array( aops ).each do | aop |
13
+ concerns = CrossConcern.get_methods rcv, Array( tgts ), **kwds
14
+ concerns.each do | tgt_concern |
15
+ _define_method_result_filter tgt_concern, aop
16
+ end
17
+ end
18
+ end
19
+
20
+ private
21
+ def _define_block_result_filter tgt_concern, blk
22
+ tgt_concern.cls.send :define_method, tgt_concern.name do |*a, &b|
23
+ blk.( tgt_concern.mthd.bind( self ).( *a, &b ), *a, &b )
24
+ end
25
+
26
+ end
27
+
28
+ def _define_method_result_filter tgt_concern, aop
29
+ tgt_concern.cls.send :define_method, tgt_concern.name do |*a, &b|
30
+ aop_method = method aop
31
+ if aop_method.arity < 0
32
+ aop_method.( tgt_concern.mthd.bind( self ).( *a, &b ), *a, &b )
33
+ else
34
+ aop_method.( tgt_concern.mthd.bind( self ).( *a, &b ), &b )
35
+ end
36
+ end
37
+ end
38
+ end # module ResultFilter
39
+ end # module AOP
40
+ end # module Lab42
@@ -0,0 +1,15 @@
1
+ module Lab42
2
+ module AOP extend self
3
+ module Tools extend self
4
+ def mk_result_wrapper bound_mthd, name
5
+ result = nil
6
+ wrapper = -> *a, &b do
7
+ wrapper.result = bound_mthd.( *a, &b )
8
+ end
9
+ Meta.add_singleton_method( wrapper, :name ){ name }
10
+ Meta.add_attribute( wrapper, :result )
11
+ end
12
+
13
+ end # module Tools
14
+ end # module AOP
15
+ end # module Lab42
@@ -0,0 +1,5 @@
1
+ module Lab42
2
+ module AOP
3
+ VERSION='0.0.1'
4
+ end # module AOP
5
+ end # module Lab42
data/lib/lab42/aop.rb ADDED
@@ -0,0 +1,63 @@
1
+ require_relative 'aop/meta'
2
+ require_relative 'aop/tools'
3
+
4
+ require_relative 'aop/cross_concern'
5
+ # require_relative 'aop/concern_scope'
6
+
7
+ require_relative 'aop/after'
8
+ require_relative 'aop/around'
9
+ require_relative 'aop/before'
10
+ require_relative 'aop/param_filter'
11
+ require_relative 'aop/result_filter'
12
+
13
+
14
+ module Lab42
15
+ module AOP
16
+ def after *args, **kwds, &blk
17
+ if blk
18
+ After.with_block( self, *args, **kwds, &blk )
19
+ else
20
+ After.with_methods( self, *args, **kwds )
21
+ end
22
+ end
23
+ def around *args, **kwds, &blk
24
+ if blk
25
+ Around.with_block( self, *args, **kwds, &blk )
26
+ else
27
+ Around.with_methods( self, *args, **kwds )
28
+ end
29
+ end
30
+ def before *args, **kwds, &blk
31
+ if blk
32
+ Before.with_block( self, *args, **kwds, &blk )
33
+ else
34
+ Before.with_methods( self, *args, **kwds )
35
+ end
36
+ end
37
+
38
+ # def concern_scope &blk
39
+ # _scopes << Module.new(&blk) # Just to know the methods defined
40
+ # module_eval &blk
41
+ # ensure
42
+ # _scopes.pop
43
+ # end
44
+
45
+ def param_filter *args, **kwds, &blk
46
+ if blk
47
+ ParamFilter.with_block( self, *args, **kwds, &blk )
48
+ else
49
+ ParamFilter.with_methods( self, *args, **kwds )
50
+ end
51
+ end
52
+
53
+ def result_filter *args, **kwds, &blk
54
+ if blk
55
+ ResultFilter.with_block( self, *args, **kwds, &blk )
56
+ else
57
+ ResultFilter.with_methods( self, *args, **kwds, &blk )
58
+ end
59
+ end
60
+
61
+ def _scopes; @__scopes__ ||= [] end
62
+ end # module AOP
63
+ end # module Lab42
metadata ADDED
@@ -0,0 +1,127 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: lab42_aop
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Robert Dober
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-09-16 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: pry
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.10'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.10'
27
+ - !ruby/object:Gem::Dependency
28
+ name: pry-nav
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.2'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.2'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: qed
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '2.9'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '2.9'
69
+ - !ruby/object:Gem::Dependency
70
+ name: ae
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '1.8'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '1.8'
83
+ description: Before, After and Around methods, either with blox or methods, à la ActiveSupport
84
+ email: robert.dober@gmail.com
85
+ executables: []
86
+ extensions: []
87
+ extra_rdoc_files: []
88
+ files:
89
+ - LICENSE
90
+ - README.md
91
+ - lib/lab42/aop.rb
92
+ - lib/lab42/aop/after.rb
93
+ - lib/lab42/aop/around.rb
94
+ - lib/lab42/aop/auto_import.rb
95
+ - lib/lab42/aop/before.rb
96
+ - lib/lab42/aop/concern_scope.rb
97
+ - lib/lab42/aop/cross_concern.rb
98
+ - lib/lab42/aop/meta.rb
99
+ - lib/lab42/aop/param_filter.rb
100
+ - lib/lab42/aop/result_filter.rb
101
+ - lib/lab42/aop/tools.rb
102
+ - lib/lab42/aop/version.rb
103
+ homepage: https://github.com/RobertDober/lab42_aop
104
+ licenses:
105
+ - MIT
106
+ metadata: {}
107
+ post_install_message:
108
+ rdoc_options: []
109
+ require_paths:
110
+ - lib
111
+ required_ruby_version: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - ">="
114
+ - !ruby/object:Gem::Version
115
+ version: '2.1'
116
+ required_rubygems_version: !ruby/object:Gem::Requirement
117
+ requirements:
118
+ - - ">="
119
+ - !ruby/object:Gem::Version
120
+ version: '0'
121
+ requirements: []
122
+ rubyforge_project:
123
+ rubygems_version: 2.2.2
124
+ signing_key:
125
+ specification_version: 4
126
+ summary: Aspect Oriented Programming with your favorite dog
127
+ test_files: []