moosex 0.0.15 → 0.0.16

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: bc3a722220a8aed4beee90b8df3a3c8194433ce2
4
- data.tar.gz: 8818053e9e74a8c21be1fb3549e3d53d8574ba24
3
+ metadata.gz: fcfa29200c1f61890442923acc7dc15d025634f0
4
+ data.tar.gz: fa879cea6cd2145c67216366c944278f09510ac6
5
5
  SHA512:
6
- metadata.gz: 17f3adf263961e0f83551cf15eb92e102f60623173533f70ddce374c72409119d4d032993760f2ada6a1884817ba3c6869104ab2531891da3e576a6249f79e87
7
- data.tar.gz: f87783b850d1e43d0be4eaaf89b66967556387406d767ae80f4709f228f75056055b92137561620a492ff94327996e5caf0885e0ff845473c35982e22c69d9af
6
+ metadata.gz: 258f22f909577942823e51962d8191c9827ed2cf4194bee1cb034a87cf056c0e83f55ce2738bd5769d4b4f021e53dd7855e623a953fe38672927aab3fa9d7833
7
+ data.tar.gz: 729fe046482be2b464dfe0f2709167737fbb88f1b28afe0b8f2215b8ce06b82fa6b38f793ac3df3a360ec11413ae37e2ba94ec8ade4b52df6599c38d454f8a10
data/Changelog CHANGED
@@ -1,3 +1,7 @@
1
+ 0.0.16 - 2013-02-07
2
+ - add currying to handles #46
3
+ - not after/before/around works well with methods who receive a block
4
+
1
5
  0.0.15 - 2013-02-07
2
6
  - after, before, around now accept more than one method name
3
7
  - add basic event support #45
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- moosex (0.0.15)
4
+ moosex (0.0.16)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/README.md CHANGED
@@ -167,12 +167,18 @@ Optional.
167
167
 
168
168
  ### coerce
169
169
 
170
- You can try to coerce the attribute value by a lambda before the type check phase. For example you can do
170
+ You can try to coerce the attribute value by a lambda/method before the type check phase. For example you can do
171
171
 
172
172
  ```ruby
173
173
  coerce: lambda{ |new_value| new_value.to_i },
174
174
  ```
175
175
 
176
+ or just
177
+
178
+ ```ruby
179
+ coerce: :to_i,
180
+ ```
181
+
176
182
  to force a convertion to integer. Or flatten one array, convert to symbol, etc. Optional.
177
183
 
178
184
  ### handles
@@ -200,6 +206,63 @@ If you need rename the method, you can specify a Hash:
200
206
  ```
201
207
 
202
208
  Optional.
209
+ #### Currying
210
+
211
+ It is possible curry constant values declaring a pair/hash and set one or more constant values / lambdas
212
+
213
+ ```ruby
214
+ handles: {
215
+ my_method_1: {
216
+ method1: 1
217
+ }
218
+ },
219
+ ```
220
+
221
+ this will curry the constant 1 to the argument list. In other words:
222
+
223
+ ```ruby
224
+ obj.target.method1(1,2,3) # OR
225
+ obj.my_method_1(2,3)
226
+ ```
227
+
228
+ are equivalent. You can curry as many arguments as you can.
229
+
230
+ ```ruby
231
+ handles: {
232
+ my_method_2: {
233
+ method2: [1, lambda{ 2 } ]
234
+ }
235
+ },
236
+ ```
237
+
238
+ will generate
239
+ ```ruby
240
+ obj.target.method1(1,2,3) # OR
241
+ obj.my_method_2(3)
242
+ ```
243
+
244
+ are equivalent. if we find one lambda we will call on runtime.
245
+
246
+ Important: if you need do something more complex ( like manipulate the argument list, etc ) consider use the hook 'around'.
247
+
248
+ ###### But how we can curry arrays?
249
+
250
+ Use Double arrays
251
+
252
+ ```ruby
253
+ handles: {
254
+ my_method_1: {
255
+ method1: [ [1,2,3] ]
256
+ }
257
+ },
258
+ ```
259
+ this will curry the array [1,2,3] to the argument list. In other words:
260
+
261
+ ```ruby
262
+ obj.target.method1([1,2,3],2,3) # OR
263
+ obj.my_method_1(2,3)
264
+ ```
265
+ are equivalent.
203
266
 
204
267
  ### trigger
205
268
 
@@ -732,7 +795,7 @@ ex3 = BuildArgsExample2.new() # x == 4, y == 8
732
795
 
733
796
  ## EVENTS
734
797
 
735
- MooseX has a built-in event system, and it should be useful if you want to avoid after/before hooks ( depends of what is yout problem ).
798
+ MooseX has a built-in event system, and it should be useful if you want to avoid after/before hooks ( depends of what is your problem ).
736
799
 
737
800
  ```ruby
738
801
  require 'moosex'
@@ -779,6 +842,55 @@ e.emit(:error, "...") # will no longer log nothing
779
842
 
780
843
  If you want to restrict how many different events you can handle, you should overload the `has_events` method and return one array of valid events. If you want accept all, you should return nil (default).
781
844
 
845
+ For example, your method should emit many events, in many points, and you can add/remove listeners easily. And Much More!
846
+
847
+ ### Events + Handles / Currying
848
+
849
+ Look this good example:
850
+
851
+ ```ruby
852
+ require 'moosex'
853
+ require 'moosex/event'
854
+
855
+ class EventHandler
856
+ include MooseX
857
+ include MooseX::Event
858
+
859
+ def has_events ; [ :pinged, :ponged ]; end
860
+ end
861
+
862
+ class EventProcessor
863
+ include MooseX
864
+
865
+ has event_handler: {
866
+ is: :ro,
867
+ isa: EventHandler,
868
+ default: lambda{ EventHandler.new }, # EventProcessor HAS ONE EventHandler
869
+ handles: { # Now, lets start to delegate and currying:
870
+ ping: { emit: :pinged }, # ping() is the same of event_handler.emit(:pinged)
871
+ pong: { emit: :ponged }, # pong(x) is the same of event_handler.emit(:pinged,x)
872
+ on_ping: { on: :pinged }, #
873
+ on_pong: { on: :ponged }, # same thing for on_ping / on_pong
874
+ },
875
+ }
876
+ end
877
+
878
+ ep = EventProcessor.new()
879
+
880
+ ep.on_ping do |obj|
881
+ puts "receive ping!"
882
+ end
883
+
884
+ ep.on_pong do |obj, message|
885
+ puts "receive pong with #{message}!"
886
+ end
887
+
888
+ ep.ping # will print "receive ping!"
889
+ ep.pong 1 # will print "receive pong with 1!"
890
+ ```
891
+
892
+ Now, imagine what you can do with a Parametrized Role: we can create all handles based on event names!
893
+
782
894
  ## IMPORTANT
783
895
 
784
896
  This module is experimental. I should test more and more to be possible consider this "production ready". If you find some issue/bug please add here: https://github.com/peczenyj/MooseX/issues
@@ -175,18 +175,18 @@ module MooseX
175
175
  after = @after[method_name]
176
176
  around = @around[method_name]
177
177
 
178
- klass.__meta_define_method(method_name) do |*args|
179
- before.each{|b| b.call(self,*args)}
178
+ klass.__meta_define_method(method_name) do |*args, &proc|
179
+ before.each{|b| b.call(self,*args, &proc)}
180
180
 
181
- original = lambda do |object, *args|
182
- method.bind(object).call(*args)
181
+ original = lambda do |object, *args, &proc|
182
+ method.bind(object).call(*args, &proc)
183
183
  end
184
184
 
185
185
  result = around.inject(original) do |lambda1, lambda2|
186
186
  lambda2.curry[lambda1]
187
- end.call(self, *args)
187
+ end.call(self, *args, &proc)
188
188
 
189
- after.each{|b| b.call(self,*args)}
189
+ after.each{|b| b.call(self,*args, &proc)}
190
190
 
191
191
  result
192
192
  end
@@ -217,9 +217,9 @@ module MooseX
217
217
  begin
218
218
  method = instance_method method_name
219
219
 
220
- define_method method_name do |*args|
221
- result = method.bind(self).call(*args)
222
- block.call(self,*args)
220
+ define_method method_name do |*args, &proc|
221
+ result = method.bind(self).call(*args, &proc)
222
+ block.call(self,*args,&proc)
223
223
  result
224
224
  end
225
225
  rescue => e
@@ -234,9 +234,9 @@ module MooseX
234
234
  begin
235
235
  method = instance_method method_name
236
236
 
237
- define_method method_name do |*args|
238
- block.call(self,*args)
239
- method.bind(self).call(*args)
237
+ define_method method_name do |*args, &proc|
238
+ block.call(self,*args, &proc)
239
+ method.bind(self).call(*args, &proc)
240
240
  end
241
241
  rescue => e
242
242
  MooseX.warn "unable to apply hook before in #{method_name} @ #{self}: #{e}", caller() if self.is_a?(Class)
@@ -248,17 +248,17 @@ module MooseX
248
248
  def around(*methods_name, &block)
249
249
  methods_name.each do |method_name|
250
250
  begin
251
+
251
252
  method = instance_method method_name
252
253
 
253
- code = Proc.new do | o, *a|
254
- method.bind(o).call(*a)
254
+ code = Proc.new do | o, *a, &proc|
255
+ method.bind(o).call(*a,&proc)
255
256
  end
256
257
 
257
- define_method method_name do |*args|
258
-
259
- block.call(code, self,*args)
260
-
261
- end
258
+ define_method method_name do |*args, &proc|
259
+ block.call(code, self,*args, &proc)
260
+ end
261
+
262
262
  rescue => e
263
263
  MooseX.warn "unable to apply hook around in #{method_name} @ #{self}: #{e}", caller() if self.is_a?(Class)
264
264
  __meta.add_around(method_name, block)
@@ -411,7 +411,15 @@ module MooseX
411
411
  end
412
412
 
413
413
  handles.map do |key,value|
414
- { key.to_sym => value.to_sym }
414
+ if value.is_a? Hash
415
+ raise "ops! Handle should accept only one map / currying" unless value.count == 1
416
+
417
+ original, currying = value.shift
418
+
419
+ { key.to_sym => [original.to_sym, currying] }
420
+ else
421
+ { key.to_sym => value.to_sym }
422
+ end
415
423
  end.reduce({}) do |hash,e|
416
424
  hash.merge(e)
417
425
  end
@@ -537,9 +545,26 @@ module MooseX
537
545
 
538
546
  attr_symbol = @attr_symbol
539
547
  @handles.each_pair do | method, target_method |
540
- @methods[method] = Proc.new do |*args|
541
- self.send(attr_symbol).send(target_method, *args)
542
- end
548
+ if target_method.is_a? Array
549
+ original, currying = target_method
550
+
551
+ @methods[method] = Proc.new do |*args, &proc|
552
+
553
+ a1 = [ currying ]
554
+
555
+ if currying.is_a?Proc
556
+ a1 = currying.call()
557
+ elsif currying.is_a? Array
558
+ a1 = currying.map{|c| (c.is_a?(Proc)) ? c.call : c }
559
+ end
560
+
561
+ self.send(attr_symbol).send(original, *a1, *args, &proc)
562
+ end
563
+ else
564
+ @methods[method] = Proc.new do |*args, &proc|
565
+ self.send(attr_symbol).send(target_method, *args, &proc)
566
+ end
567
+ end
543
568
  end
544
569
  end
545
570
 
@@ -59,8 +59,7 @@ module MooseX
59
59
  listener
60
60
  end
61
61
 
62
- before(:add_event_listener, :emit) do |obj, event, *rest|
63
-
62
+ before(:on, :once, :emit) do |obj, event, *rest, &proc|
64
63
  if ! obj.has_events.nil? && ! [ obj.has_events ].flatten.include?(event)
65
64
 
66
65
  raise EventException, "Event '#{event.inspect}' not supported, this class only allow: #{obj.has_events.inspect}",caller
@@ -1,3 +1,3 @@
1
1
  module MooseX
2
- VERSION = "0.0.15"
2
+ VERSION = "0.0.16"
3
3
  end
@@ -0,0 +1,40 @@
1
+ require 'moosex'
2
+ require 'moosex/event'
3
+
4
+ class EventHandler
5
+ include MooseX
6
+ include MooseX::Event
7
+
8
+ def has_events
9
+ [ :pinged, :ponged ]
10
+ end
11
+ end
12
+
13
+ class EventProcessor
14
+ include MooseX
15
+
16
+ has event_handler: {
17
+ is: :ro,
18
+ isa: EventHandler,
19
+ default: lambda{ EventHandler.new },
20
+ handles: {
21
+ ping: { emit: :pinged },
22
+ pong: { emit: :ponged },
23
+ on_ping: { on: :pinged },
24
+ on_pong: { on: :ponged },
25
+ },
26
+ }
27
+ end
28
+
29
+ ep = EventProcessor.new()
30
+
31
+ ep.on_ping do |x|
32
+ puts "receive ping!"
33
+ end
34
+
35
+ ep.on_pong do |obj, message|
36
+ puts "receive pong with #{message}!"
37
+ end
38
+
39
+ ep.ping # will print "receive ping!"
40
+ ep.pong 1 # will print "receive pong!"
@@ -12,7 +12,7 @@ class CoerceTest
12
12
  has attribute_rw: {
13
13
  is: :rw,
14
14
  isa: Integer,
15
- coerce: lambda {|value| value.to_i },
15
+ coerce: :to_i,
16
16
  }
17
17
 
18
18
  has attribute_lazy: {
@@ -161,4 +161,4 @@ describe EventExample2 do
161
161
 
162
162
  e.emit(:xxx)
163
163
  end
164
- end
164
+ end
@@ -120,4 +120,98 @@ describe "OtherPoint4D" do
120
120
  p.z.should == 0
121
121
  p.t.should == 0
122
122
  end
123
- end
123
+ end
124
+
125
+ module ModuleHWB
126
+ include MooseX
127
+
128
+ requires :info
129
+
130
+ around(:call_with) do |original, object,x,&proc|
131
+ object.info(1,x)
132
+
133
+ result= original.call(object,x,&proc)
134
+
135
+ object.info(2,result)
136
+
137
+ result
138
+ end
139
+
140
+ before(:call_with) do |object,x, &k|
141
+ object.info(3, x)
142
+ end
143
+
144
+ after(:call_with) do |object,x,&k|
145
+ object.info(4, x)
146
+ end
147
+ end
148
+
149
+ class HooksWithBlocks
150
+ include MooseX
151
+
152
+ has logger: { is: :rw, handles: :info }
153
+
154
+ def call_with(x)
155
+ yield(x)
156
+ #proc.call(x)
157
+ end
158
+
159
+ include ModuleHWB
160
+ end
161
+
162
+ class HooksWithBlocks2
163
+ include MooseX
164
+
165
+ has logger: { is: :rw, handles: :info }
166
+
167
+ def call_with(x, &proc)
168
+ #yield(x)
169
+ proc.call(x)
170
+ end
171
+
172
+ around(:call_with) do |original, object,x,&proc|
173
+ object.info(1,x)
174
+
175
+ result= original.call(object,x,&proc)
176
+
177
+ object.info(2,result)
178
+
179
+ result
180
+ end
181
+
182
+ before(:call_with) do |object,x, &k|
183
+ object.info(3, x)
184
+ end
185
+
186
+ after(:call_with) do |object,x,&k|
187
+ object.info(4, x)
188
+ end
189
+ end
190
+
191
+ describe HooksWithBlocks do
192
+ it "should call all hooks" do
193
+ logger = double
194
+ logger.should_receive(:info).with(3,7).once()
195
+ logger.should_receive(:info).with(1,7).once()
196
+ logger.should_receive(:info).with(2,8).once()
197
+ logger.should_receive(:info).with(4,7).once()
198
+
199
+ x = HooksWithBlocks.new(logger: logger)
200
+ x.call_with(7){|x| x+1}
201
+ end
202
+ end
203
+
204
+ describe HooksWithBlocks2 do
205
+ it "should call all hooks" do
206
+ logger = double
207
+ logger.should_receive(:info).with(3,7).once()
208
+ logger.should_receive(:info).with(1,7).once()
209
+ logger.should_receive(:info).with(2,8).once()
210
+ logger.should_receive(:info).with(4,7).once()
211
+
212
+ x = HooksWithBlocks2.new(logger: logger)
213
+ x.call_with(7) do |x|
214
+ x+1
215
+ end
216
+ end
217
+ end
@@ -5,17 +5,37 @@ class ProxyToTarget
5
5
 
6
6
  has target: {
7
7
  is: :ro,
8
- default: lambda { Target.new }, # default, new instace of Target
9
- handles: { # handles is for delegation,
10
- my_method_x: :method_x, # inject methods with new names
11
- my_method_y: :method_y, # old => obj.target.method_x
12
- }, # now => obj.my_method_x
8
+ default: lambda { Target.new }, # default, new instace of Target
9
+ handles: { # handles is for delegation,
10
+ my_method_x: :method_x, # inject methods with new names
11
+ my_method_y: :method_y, # old => obj.target.method_x , now => obj.my_method_x
12
+ my_method_y_with_1: { # currying!!!
13
+ method_y: 1, # call obj.mymethod_z(2,3) is the equivalent to
14
+ }, # call obj.target.method_z(1,2,3)
15
+ my_method_y_with_lambda: { # currying!!!
16
+ method_y: lambda{ 1 }, # call obj.mymethod_z(2,3) is the equivalent to
17
+ }, # call obj.target.method_z(1,2,3)
18
+ my_method_z_with_array: {
19
+ method_z: [1,lambda{ 2 } ,3]
20
+ },
21
+ my_method_k_with_literal_array: {
22
+ method_k: [[1,2,3]]
23
+ },
24
+ my_method_k_with_literal_array2: {
25
+ method_k: [ lambda{ [1,2,3] } ]
26
+ },
27
+ my_method_k_with_literal_array3: {
28
+ method_k: lambda{ [[1,2,3]] }
29
+ }
30
+ }
13
31
  }
14
32
  end
15
33
 
16
34
  module TargetModule
17
35
  def method_x; 1024; end # works with simple methods
18
36
  def method_y(a,b,c); a + b + c; end # or methods with arguments
37
+ def method_z(*args); args.reduce(:+); end
38
+ def method_k(array); array.count; end
19
39
  end
20
40
 
21
41
  class Target
@@ -36,7 +56,48 @@ describe "ProxyToTarget" do
36
56
  p.target.method_y(1,2,3).should == 6
37
57
  p.my_method_y(1,2,3).should == 6
38
58
  end
59
+
60
+ it "should delegate method_y to the target with currying" do
61
+ p = ProxyToTarget.new
62
+
63
+ p.target.method_y(1,2,3).should == 6
64
+ p.my_method_y_with_1(2,3).should == 6
65
+ end
66
+
67
+ it "should delegate method_y to the target with currying as lambda" do
68
+ p = ProxyToTarget.new
69
+
70
+ p.target.method_y(1,2,3).should == 6
71
+ p.my_method_y_with_lambda(2,3).should == 6
72
+ end
73
+
74
+ it "should delegate method_z to the target with currying (many args) as lambda" do
75
+ p = ProxyToTarget.new
76
+
77
+ p.target.method_z(1,2,3,4).should == 10
78
+ p.my_method_z_with_array(4).should == 10
79
+ end
80
+
81
+ it "should delegate method_k to the target with currying (many args)" do
82
+ p = ProxyToTarget.new
83
+
84
+ p.target.method_k([1,2,3]).should == 3
85
+ p.my_method_k_with_literal_array().should == 3
86
+ end
39
87
 
88
+ it "should delegate method_k to the target with currying (many args) as lambda" do
89
+ p = ProxyToTarget.new
90
+
91
+ p.target.method_k([1,2,3]).should == 3
92
+ p.my_method_k_with_literal_array2().should == 3
93
+ end
94
+
95
+ it "should delegate method_k to the target with currying (many args) as lambda (2)" do
96
+ p = ProxyToTarget.new
97
+
98
+ p.target.method_k([1,2,3]).should == 3
99
+ p.my_method_k_with_literal_array3().should == 3
100
+ end
40
101
  it "should inject method_y" do
41
102
  p = ProxyToTarget.new
42
103
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: moosex
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.15
4
+ version: 0.0.16
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tiago Peczenyj
@@ -91,6 +91,7 @@ files:
91
91
  - lib/moosex/types.rb
92
92
  - lib/moosex/version.rb
93
93
  - moosex.gemspec
94
+ - samples/events.rb
94
95
  - samples/point.rb
95
96
  - samples/roles.rb
96
97
  - spec/baserole_spec.rb