aop 0.0.2 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +24 -4
- data/lib/aop/pointcut.rb +18 -6
- data/lib/aop/version.rb +1 -1
- data/spec/aop/advanced_spec.rb +110 -0
- data/spec/aop/around_spec.rb +27 -0
- data/spec/fixtures/bank_account.rb +10 -0
- data/spec/fixtures/cash_account.rb +16 -0
- metadata +8 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 265bbfbbde5fedca853374f381977f960186c174
|
4
|
+
data.tar.gz: 5ba07e066d01dfb9647f8294f29b1508604fe2ea
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4e762bcad98bbbf72d5f867d22bb20e1add43d02a66e0f63f1da21c1804b335b539bee2eea2c2956c0a7900153931285052a4ee21413bc78e620575c0caefb79
|
7
|
+
data.tar.gz: aa177e07c23669b04a02ac5de5e4ca9bedb2dacc7e92dd8124419b63fd5d5924fa0d236fee9dc01471ec32c8a3454e20cb19f59eb1c9e3b8c77cf1cb969092df
|
data/README.md
CHANGED
@@ -50,8 +50,6 @@ end
|
|
50
50
|
|
51
51
|
### Around advice
|
52
52
|
|
53
|
-
*Not implemented*
|
54
|
-
|
55
53
|
```ruby
|
56
54
|
module Transactional
|
57
55
|
Aop["BankAccount#transfer:around"].advice do |joint_point, account, *args, &blk|
|
@@ -62,9 +60,31 @@ module Transactional
|
|
62
60
|
end
|
63
61
|
```
|
64
62
|
|
65
|
-
|
63
|
+
### Class methods
|
64
|
+
|
65
|
+
Use `.method` notation:
|
66
|
+
|
67
|
+
```ruby
|
68
|
+
module Transactional
|
69
|
+
Aop["BankAccount.transfer:around"].advice do |joint_point, klass, *args, &blk|
|
70
|
+
start_transaction
|
71
|
+
joint_point.call
|
72
|
+
finish_transaction
|
73
|
+
end
|
74
|
+
end
|
75
|
+
```
|
76
|
+
|
77
|
+
### Multiple classes, methods and advices
|
66
78
|
|
67
|
-
|
79
|
+
Use `,` to use multiple classes, methods and advices:
|
80
|
+
|
81
|
+
```ruby
|
82
|
+
module Analytics
|
83
|
+
Aop["User,Admin#sign_in,.sign_up,#sign_out:before,:after"].advice do |target, *args, &blk|
|
84
|
+
report("auth_action", user.id)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
```
|
68
88
|
|
69
89
|
## Contributing
|
70
90
|
|
data/lib/aop/pointcut.rb
CHANGED
@@ -13,16 +13,16 @@ module Aop
|
|
13
13
|
@class_names = @class_spec.split(",")
|
14
14
|
@classes = @class_names.map { |name| Object.const_get(name) }
|
15
15
|
|
16
|
-
@method_spec = spec.scan(/[#\.][
|
16
|
+
@method_spec = spec.scan(/[#\.][^,#\.:]+/)
|
17
17
|
@methods = @method_spec.map { |m| MethodReference.from(m) }
|
18
18
|
|
19
|
-
@advices = spec.scan(/[^:]:([
|
19
|
+
@advices = spec.scan(/[^:]:([^:,]+)/).flatten
|
20
20
|
end
|
21
21
|
|
22
22
|
def advice(&advised)
|
23
|
-
advices
|
24
|
-
advices.each do |advice|
|
25
|
-
|
23
|
+
return _advice(@advices.first, advised) if @advices.count == 1
|
24
|
+
@advices.each do |advice|
|
25
|
+
Aop["#{@class_names.join(",")}#{@method_spec.join(",")}:#{advice}"].advice(&advised)
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
@@ -30,6 +30,7 @@ module Aop
|
|
30
30
|
|
31
31
|
def _advice(advice, advised)
|
32
32
|
return before_advice(advised) if advice == "before"
|
33
|
+
return around_advice(advised) if advice == "around"
|
33
34
|
after_advice(advised)
|
34
35
|
end
|
35
36
|
|
@@ -63,6 +64,17 @@ module Aop
|
|
63
64
|
end
|
64
65
|
end
|
65
66
|
|
67
|
+
def around_advice(advised)
|
68
|
+
generic_advice(advised) do |method_ref|
|
69
|
+
lambda do |*args, &blk|
|
70
|
+
result = nil
|
71
|
+
joint_point = lambda { result = method_ref.call(self, *args, &blk) }
|
72
|
+
advised.call(joint_point, self, *args, &blk)
|
73
|
+
result
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
66
78
|
class MethodReference
|
67
79
|
def self.from(m)
|
68
80
|
return new(m) if m[0...1] == "#"
|
@@ -83,7 +95,7 @@ module Aop
|
|
83
95
|
end
|
84
96
|
|
85
97
|
def call(target, *args, &blk)
|
86
|
-
|
98
|
+
target.send(alias_name, *args, &blk)
|
87
99
|
end
|
88
100
|
|
89
101
|
private
|
data/lib/aop/version.rb
CHANGED
@@ -0,0 +1,110 @@
|
|
1
|
+
RSpec.describe "Advanced advices" do
|
2
|
+
include FixtureLoader
|
3
|
+
|
4
|
+
let(:spy) { double("Spy") }
|
5
|
+
|
6
|
+
before do
|
7
|
+
load_fixture("BankAccount", "bank_account")
|
8
|
+
load_fixture("CashAccount", "cash_account")
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "class methods" do
|
12
|
+
before do
|
13
|
+
Aop["BankAccount.transfer:around"].advice do |joint_point, klass, *args, &blk|
|
14
|
+
spy.before(klass, *args, &blk)
|
15
|
+
joint_point.call
|
16
|
+
spy.after(klass, *args, &blk)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
it "fires around #transfer" do
|
21
|
+
account = BankAccount.new(spy)
|
22
|
+
other = BankAccount.new(spy)
|
23
|
+
amount = 55
|
24
|
+
|
25
|
+
expect(spy).to receive(:before).with(BankAccount, spy, account, other, amount).ordered.once
|
26
|
+
expect(spy).to receive(:inside).with(spy, account, other, amount).ordered.once
|
27
|
+
expect(spy).to receive(:after).with(BankAccount, spy, account, other, amount).ordered.once
|
28
|
+
|
29
|
+
expect(BankAccount.transfer(spy, account, other, amount)).to eq(:a_result)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "multiple classes, methods and advices" do
|
34
|
+
before do
|
35
|
+
Aop["BankAccount,CashAccount#transfer,#withdraw,.transfer:before,:after"].advice do |*args, &blk|
|
36
|
+
spy.report(*args, &blk)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
it "works for BankAccount#transfer" do
|
41
|
+
account = BankAccount.new(spy)
|
42
|
+
other = BankAccount.new(spy)
|
43
|
+
amount = 55
|
44
|
+
|
45
|
+
expect(spy).to receive(:report).with(account, other, amount).ordered.once
|
46
|
+
expect(spy).to receive(:inside).with(other, amount).ordered.once
|
47
|
+
expect(spy).to receive(:report).with(account, other, amount).ordered.once
|
48
|
+
|
49
|
+
expect(account.transfer(other, amount)).to eq(:a_result)
|
50
|
+
end
|
51
|
+
|
52
|
+
it "works for CashAccount#transfer" do
|
53
|
+
account = CashAccount.new(spy)
|
54
|
+
other = CashAccount.new(spy)
|
55
|
+
amount = 55
|
56
|
+
|
57
|
+
expect(spy).to receive(:report).with(account, other, amount).ordered.once
|
58
|
+
expect(spy).to receive(:inside).with(:cash_account, other, amount).ordered.once
|
59
|
+
expect(spy).to receive(:report).with(account, other, amount).ordered.once
|
60
|
+
|
61
|
+
expect(account.transfer(other, amount)).to eq(:a_result)
|
62
|
+
end
|
63
|
+
|
64
|
+
it "works for BankAccount#withdraw" do
|
65
|
+
account = BankAccount.new(spy)
|
66
|
+
amount = 55
|
67
|
+
|
68
|
+
expect(spy).to receive(:report).with(account, amount).ordered.once
|
69
|
+
expect(spy).to receive(:withdraw).with(account, amount).ordered.once
|
70
|
+
expect(spy).to receive(:report).with(account, amount).ordered.once
|
71
|
+
|
72
|
+
expect(account.withdraw(amount)).to eq(:a_result)
|
73
|
+
end
|
74
|
+
|
75
|
+
it "works for CashAccount#withdraw" do
|
76
|
+
account = CashAccount.new(spy)
|
77
|
+
amount = 55
|
78
|
+
|
79
|
+
expect(spy).to receive(:report).with(account, amount).ordered.once
|
80
|
+
expect(spy).to receive(:withdraw).with(:cash_account, account, amount).ordered.once
|
81
|
+
expect(spy).to receive(:report).with(account, amount).ordered.once
|
82
|
+
|
83
|
+
expect(account.withdraw(amount)).to eq(:a_result)
|
84
|
+
end
|
85
|
+
|
86
|
+
it "works for BankAccount.transfer" do
|
87
|
+
account = BankAccount.new(spy)
|
88
|
+
other = BankAccount.new(spy)
|
89
|
+
amount = 55
|
90
|
+
|
91
|
+
expect(spy).to receive(:report).with(BankAccount, spy, account, other, amount).ordered.once
|
92
|
+
expect(spy).to receive(:inside).with(spy, account, other, amount).ordered.once
|
93
|
+
expect(spy).to receive(:report).with(BankAccount, spy, account, other, amount).ordered.once
|
94
|
+
|
95
|
+
expect(BankAccount.transfer(spy, account, other, amount)).to eq(:a_result)
|
96
|
+
end
|
97
|
+
|
98
|
+
it "works for CashAccount.transfer" do
|
99
|
+
account = CashAccount.new(spy)
|
100
|
+
other = CashAccount.new(spy)
|
101
|
+
amount = 55
|
102
|
+
|
103
|
+
expect(spy).to receive(:report).with(CashAccount, spy, account, other, amount).ordered.once
|
104
|
+
expect(spy).to receive(:inside).with(:cash_account, spy, account, other, amount).ordered.once
|
105
|
+
expect(spy).to receive(:report).with(CashAccount, spy, account, other, amount).ordered.once
|
106
|
+
|
107
|
+
expect(CashAccount.transfer(spy, account, other, amount)).to eq(:a_result)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
RSpec.describe "Around advice" do
|
2
|
+
include FixtureLoader
|
3
|
+
|
4
|
+
let(:spy) { double("Spy") }
|
5
|
+
|
6
|
+
before do
|
7
|
+
load_fixture("BankAccount", "bank_account")
|
8
|
+
|
9
|
+
Aop["BankAccount#transfer:around"].advice do |joint_point, account, *args, &blk|
|
10
|
+
spy.before(account, *args, &blk)
|
11
|
+
joint_point.call
|
12
|
+
spy.after(account, *args, &blk)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
it "fires around #transfer" do
|
17
|
+
account = BankAccount.new(spy)
|
18
|
+
other = BankAccount.new(spy)
|
19
|
+
amount = 55
|
20
|
+
|
21
|
+
expect(spy).to receive(:before).with(account, other, amount).ordered.once
|
22
|
+
expect(spy).to receive(:inside).with(other, amount).ordered.once
|
23
|
+
expect(spy).to receive(:after).with(account, other, amount).ordered.once
|
24
|
+
|
25
|
+
expect(account.transfer(other, amount)).to eq(:a_result)
|
26
|
+
end
|
27
|
+
end
|
@@ -3,4 +3,14 @@ class BankAccount < Struct.new(:spy)
|
|
3
3
|
spy.inside(to, amount)
|
4
4
|
:a_result
|
5
5
|
end
|
6
|
+
|
7
|
+
def withdraw(amount)
|
8
|
+
spy.withdraw(self, amount)
|
9
|
+
:a_result
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.transfer(spy, from, to, amount)
|
13
|
+
spy.inside(spy, from, to, amount)
|
14
|
+
:a_result
|
15
|
+
end
|
6
16
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class CashAccount < Struct.new(:spy)
|
2
|
+
def transfer(to, amount)
|
3
|
+
spy.inside(:cash_account, to, amount)
|
4
|
+
:a_result
|
5
|
+
end
|
6
|
+
|
7
|
+
def withdraw(amount)
|
8
|
+
spy.withdraw(:cash_account, self, amount)
|
9
|
+
:a_result
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.transfer(spy, from, to, amount)
|
13
|
+
spy.inside(:cash_account, spy, from, to, amount)
|
14
|
+
:a_result
|
15
|
+
end
|
16
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: aop
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alex Fedorov
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-02-
|
11
|
+
date: 2015-02-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -56,9 +56,12 @@ files:
|
|
56
56
|
- lib/aop.rb
|
57
57
|
- lib/aop/pointcut.rb
|
58
58
|
- lib/aop/version.rb
|
59
|
+
- spec/aop/advanced_spec.rb
|
59
60
|
- spec/aop/after_spec.rb
|
61
|
+
- spec/aop/around_spec.rb
|
60
62
|
- spec/aop/before_spec.rb
|
61
63
|
- spec/fixtures/bank_account.rb
|
64
|
+
- spec/fixtures/cash_account.rb
|
62
65
|
- spec/spec_helper.rb
|
63
66
|
- spec/support/loader.rb
|
64
67
|
homepage: https://github.com/waterlink/aop
|
@@ -86,8 +89,11 @@ signing_key:
|
|
86
89
|
specification_version: 4
|
87
90
|
summary: Very thin AOP gem for Ruby
|
88
91
|
test_files:
|
92
|
+
- spec/aop/advanced_spec.rb
|
89
93
|
- spec/aop/after_spec.rb
|
94
|
+
- spec/aop/around_spec.rb
|
90
95
|
- spec/aop/before_spec.rb
|
91
96
|
- spec/fixtures/bank_account.rb
|
97
|
+
- spec/fixtures/cash_account.rb
|
92
98
|
- spec/spec_helper.rb
|
93
99
|
- spec/support/loader.rb
|