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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: af9f44c8cac54ec4197e54a135d3c6829b8badd6
4
- data.tar.gz: f9ffd78f10555e9ef4f09c2d14231d7248f4c82f
3
+ metadata.gz: 265bbfbbde5fedca853374f381977f960186c174
4
+ data.tar.gz: 5ba07e066d01dfb9647f8294f29b1508604fe2ea
5
5
  SHA512:
6
- metadata.gz: f24dd40907b9bd09ac43e491651cfb64cedaa4044363d99fba028e3b23c85afe2a5d1a12baa6d2c440a6e7dec0aec8f65413048753584183cb63efb8a8451b2a
7
- data.tar.gz: af8f883d3f73072302b052afd3e69cca24d4d5d0517bb404cb30c68bc9f9be906e987aa3e1a596c9d3e625a96e028a28c5f7166708f405e66aa184b23282ca71
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
- ## TODO (to specify)
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
- - multiple classes, methods and types of advices at once
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(/[^:]:([^:]+)/).flatten
19
+ @advices = spec.scan(/[^:]:([^:,]+)/).flatten
20
20
  end
21
21
 
22
22
  def advice(&advised)
23
- advices = @advices
24
- advices.each do |advice|
25
- _advice(advice, advised)
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
- alias_target(target).send(alias_name, *args, &blk)
98
+ target.send(alias_name, *args, &blk)
87
99
  end
88
100
 
89
101
  private
data/lib/aop/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Aop
2
- VERSION = "0.0.2"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -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.2
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-07 00:00:00.000000000 Z
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