moosex 0.0.14 → 0.0.15
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Changelog +6 -0
- data/Gemfile.lock +1 -1
- data/README.md +108 -9
- data/lib/moosex.rb +94 -53
- data/lib/moosex/event.rb +71 -0
- data/lib/moosex/version.rb +1 -1
- data/spec/event_spec.rb +164 -0
- data/spec/parametric_role_spec.rb +174 -0
- data/spec/role_spec.rb +1 -0
- metadata +7 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bc3a722220a8aed4beee90b8df3a3c8194433ce2
|
4
|
+
data.tar.gz: 8818053e9e74a8c21be1fb3549e3d53d8574ba24
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 17f3adf263961e0f83551cf15eb92e102f60623173533f70ddce374c72409119d4d032993760f2ada6a1884817ba3c6869104ab2531891da3e576a6249f79e87
|
7
|
+
data.tar.gz: f87783b850d1e43d0be4eaaf89b66967556387406d767ae80f4709f228f75056055b92137561620a492ff94327996e5caf0885e0ff845473c35982e22c69d9af
|
data/Changelog
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
0.0.15 - 2013-02-07
|
2
|
+
- after, before, around now accept more than one method name
|
3
|
+
- add basic event support #45
|
4
|
+
- add parametric roles #44
|
5
|
+
- add init method to enable warnings and exceptions #43
|
6
|
+
|
1
7
|
0.0.14 - 2013-02-05
|
2
8
|
- roles with around/before/after basic support #41
|
3
9
|
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -587,7 +587,7 @@ Roles are Modules with steroids. If you include the MooseX module in another mod
|
|
587
587
|
require 'moosex'
|
588
588
|
|
589
589
|
module Eq
|
590
|
-
include MooseX
|
590
|
+
include MooseX
|
591
591
|
|
592
592
|
requires :equal
|
593
593
|
|
@@ -603,11 +603,10 @@ module Valuable
|
|
603
603
|
end
|
604
604
|
|
605
605
|
class Currency
|
606
|
-
include Valuable
|
607
|
-
include Eq # will warn
|
608
|
-
#
|
609
|
-
|
610
|
-
|
606
|
+
include Valuable.init(warnings: false) # default is true!
|
607
|
+
include Eq # default will warn about equal missing.
|
608
|
+
# alternative: include after equal definition!
|
609
|
+
|
611
610
|
def equal(other)
|
612
611
|
self.value == other.value
|
613
612
|
end
|
@@ -622,14 +621,65 @@ c1.equal(c2) # true, they have the same value
|
|
622
621
|
c1.no_equal(c2) # will return false
|
623
622
|
```
|
624
623
|
|
625
|
-
Roles can support has to describe attributes, and you can reuse code easily.
|
626
|
-
|
627
|
-
For example, we can add a 'after' block for no_equal inside Eq, but not for equal - this limitation will be fixed soon (see issue #41 @ github).
|
624
|
+
Roles can support has to describe attributes, and you can reuse code easily.
|
628
625
|
|
629
626
|
### requires
|
630
627
|
|
631
628
|
You can also mark one or more methods as 'required'. When you do this, we will raise one exception if you try to create a new instance and the class does not implement it. It is a safe way to create interfaces or abstract classes. It uses respond_to? to verify.
|
632
629
|
|
630
|
+
|
631
|
+
## Parametric Roles
|
632
|
+
|
633
|
+
Parametric roles is a good way of reuse code based on roles. For example, to create one or more attributes in the class who includes our role, we just add the code to be executed in the on_init hook.
|
634
|
+
|
635
|
+
```ruby
|
636
|
+
module EasyCrud
|
637
|
+
include MooseX
|
638
|
+
|
639
|
+
on_init do |*attributes|
|
640
|
+
attributes.each do | attr |
|
641
|
+
has attr, { is: :rw, predicate: "has_attr_#{attr}_or_not?" }
|
642
|
+
end
|
643
|
+
end
|
644
|
+
end
|
645
|
+
|
646
|
+
class LogTest
|
647
|
+
include EasyCrud.init(:a, :b)
|
648
|
+
...
|
649
|
+
```
|
650
|
+
|
651
|
+
when we call `init` with arguments, we will call all on_init blocks defined in the role. In this example we inject attributes 'a' and 'b' with reader/writter and a predicate based on the name ex: `has_attr_a_or_not?`
|
652
|
+
|
653
|
+
### composable parametric roles
|
654
|
+
|
655
|
+
To combine one or more parametric roles to another parametric role you should do something like this:
|
656
|
+
|
657
|
+
```ruby
|
658
|
+
module Logabble2
|
659
|
+
include MooseX
|
660
|
+
|
661
|
+
on_init do |args|
|
662
|
+
args[:klass] = self
|
663
|
+
include Logabble.init(args)
|
664
|
+
end
|
665
|
+
end
|
666
|
+
|
667
|
+
module Logabble
|
668
|
+
include MooseX
|
669
|
+
|
670
|
+
on_init do | args |
|
671
|
+
|
672
|
+
klass = args[:klass] || self # <= THIS will guarantee you will
|
673
|
+
methods = args[:methods] || [] # modify the right class
|
674
|
+
|
675
|
+
methods.each do |method|
|
676
|
+
klass.around(method) do |original, object, *args|
|
677
|
+
# add log around method
|
678
|
+
# call original method
|
679
|
+
# return
|
680
|
+
...
|
681
|
+
```
|
682
|
+
|
633
683
|
## BUILD
|
634
684
|
|
635
685
|
If you need run some code after the creation of the object (like some extra validation), you should implement the BUILD method.
|
@@ -680,6 +730,55 @@ ex2 = BuildArgsExample2.new(1) # x == 1, y == 8
|
|
680
730
|
ex3 = BuildArgsExample2.new() # x == 4, y == 8
|
681
731
|
```
|
682
732
|
|
733
|
+
## EVENTS
|
734
|
+
|
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 ).
|
736
|
+
|
737
|
+
```ruby
|
738
|
+
require 'moosex'
|
739
|
+
require 'moosex/event'
|
740
|
+
|
741
|
+
class Example
|
742
|
+
include MooseX
|
743
|
+
include MooseX::Event
|
744
|
+
|
745
|
+
def ping
|
746
|
+
self.emit(:pinged)
|
747
|
+
end
|
748
|
+
end
|
749
|
+
|
750
|
+
e = Example.new
|
751
|
+
|
752
|
+
e.on(:pinged) do |object|
|
753
|
+
puts "Ping!"
|
754
|
+
end
|
755
|
+
|
756
|
+
e.once(:pinged) do |object|
|
757
|
+
puts "Ping Once!"
|
758
|
+
end
|
759
|
+
|
760
|
+
e.ping # will print two messages, "Ping!" and "Ping Once!"
|
761
|
+
e.ping # will print just "Ping!"
|
762
|
+
|
763
|
+
e.remove_all_listeners(:pinged)
|
764
|
+
|
765
|
+
e.ping # will no longer print nothing
|
766
|
+
|
767
|
+
# you can use arguments
|
768
|
+
# consider you have one logger attribute in this example
|
769
|
+
listener = e.on(:error) do |obj, message|
|
770
|
+
obj.logger.fatal("Error: #{message}")
|
771
|
+
end
|
772
|
+
|
773
|
+
e.emit(:error, "ops") # will log, as fatal, "Error: ops"
|
774
|
+
|
775
|
+
e.remove_listener( error: listener )
|
776
|
+
|
777
|
+
e.emit(:error, "...") # will no longer log nothing
|
778
|
+
```
|
779
|
+
|
780
|
+
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
|
+
|
683
782
|
## IMPORTANT
|
684
783
|
|
685
784
|
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
|
data/lib/moosex.rb
CHANGED
@@ -9,17 +9,28 @@ require "moosex/version"
|
|
9
9
|
require "moosex/types"
|
10
10
|
|
11
11
|
module MooseX
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
12
|
+
@@MOOSEX_WARNINGS = true
|
13
|
+
@@MOOSEX_FATAL = false
|
14
|
+
|
15
|
+
class FatalError < StandardError
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.warn(x, *c)
|
19
|
+
raise FatalError, "[MooseX] exception: #{x}",*c if @@MOOSEX_FATAL
|
20
|
+
Kernel.warn("[MooseX] warning: #{x}") if @@MOOSEX_WARNINGS
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.init(args={})
|
24
|
+
if args.has_key? :warnings
|
25
|
+
@@MOOSEX_WARNINGS = !! args[:warnings]
|
26
|
+
end
|
27
|
+
|
28
|
+
if args.has_key? :fatal
|
29
|
+
@@MOOSEX_FATAL = !! args[:fatal]
|
30
|
+
end
|
31
|
+
|
32
|
+
self
|
33
|
+
end
|
23
34
|
|
24
35
|
class RequiredMethodNotFoundError < NameError
|
25
36
|
end
|
@@ -27,8 +38,15 @@ module MooseX
|
|
27
38
|
def MooseX.included(c)
|
28
39
|
|
29
40
|
c.extend(MooseX::Core)
|
41
|
+
|
42
|
+
def c.init(*args)
|
43
|
+
__meta.roles.each{|role| role.call(*args)}
|
44
|
+
|
45
|
+
self
|
46
|
+
end
|
30
47
|
|
31
48
|
def c.included(x)
|
49
|
+
|
32
50
|
MooseX.included(x)
|
33
51
|
x.__meta.load_from(self.__meta)
|
34
52
|
|
@@ -39,7 +57,7 @@ module MooseX
|
|
39
57
|
|
40
58
|
x.__meta.requires.each do |method|
|
41
59
|
unless x.public_instance_methods.include? method
|
42
|
-
warn "
|
60
|
+
MooseX.warn "you must implement method '#{method}' in #{x} #{x.class}: required"# if $MOOSEX_DEBUG
|
43
61
|
end
|
44
62
|
end
|
45
63
|
end
|
@@ -80,12 +98,13 @@ module MooseX
|
|
80
98
|
end
|
81
99
|
|
82
100
|
class Meta
|
83
|
-
attr_reader :attrs, :requires, :before, :after, :around
|
101
|
+
attr_reader :attrs, :requires, :before, :after, :around, :roles
|
84
102
|
|
85
103
|
def initialize(old_meta=nil)
|
86
104
|
@initialized = false
|
87
105
|
@attrs = {}
|
88
106
|
@requires = []
|
107
|
+
@roles = []
|
89
108
|
@before = Hash.new { |hash, key| hash[key] = [] }
|
90
109
|
@after = Hash.new { |hash, key| hash[key] = [] }
|
91
110
|
@around = Hash.new { |hash, key| hash[key] = [] }
|
@@ -136,13 +155,22 @@ module MooseX
|
|
136
155
|
def add_around(method_name, block)
|
137
156
|
@around[method_name] << block.clone
|
138
157
|
end
|
158
|
+
|
159
|
+
def add_role(block)
|
160
|
+
@roles << block
|
161
|
+
end
|
139
162
|
|
140
163
|
def init_klass(klass)
|
141
164
|
#return if @initialized
|
142
165
|
|
143
166
|
[@before.keys + @after.keys + @around.keys].flatten.uniq.each do |method_name|
|
144
|
-
|
145
|
-
|
167
|
+
begin
|
168
|
+
method = klass.instance_method method_name
|
169
|
+
rescue => e
|
170
|
+
MooseX.warn "Unable to apply hooks (after/before/around) in #{klass}::#{method_name} : #{e}" # if $MOOSEX_DEBUG
|
171
|
+
next
|
172
|
+
end
|
173
|
+
|
146
174
|
before = @before[method_name]
|
147
175
|
after = @after[method_name]
|
148
176
|
around = @around[method_name]
|
@@ -168,7 +196,7 @@ module MooseX
|
|
168
196
|
def init(object, args)
|
169
197
|
@attrs.each_pair{ |symbol, attr| attr.init(object, args) }
|
170
198
|
|
171
|
-
warn "
|
199
|
+
MooseX.warn "unused attributes #{args} for #{object.class}", caller unless args.empty?
|
172
200
|
|
173
201
|
@requires.each do |method|
|
174
202
|
unless object.respond_to? method
|
@@ -180,49 +208,62 @@ module MooseX
|
|
180
208
|
end
|
181
209
|
|
182
210
|
module Core
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
211
|
+
def on_init(&block)
|
212
|
+
__meta.add_role(block)
|
213
|
+
end
|
214
|
+
|
215
|
+
def after(*methods_name, &block)
|
216
|
+
methods_name.each do |method_name|
|
217
|
+
begin
|
218
|
+
method = instance_method method_name
|
219
|
+
|
220
|
+
define_method method_name do |*args|
|
221
|
+
result = method.bind(self).call(*args)
|
222
|
+
block.call(self,*args)
|
223
|
+
result
|
224
|
+
end
|
225
|
+
rescue => e
|
226
|
+
MooseX.warn "unable to apply hook after in #{method_name} @ #{self}: #{e}", caller() if self.is_a?(Class)
|
227
|
+
__meta.add_after(method_name, block)
|
228
|
+
end
|
229
|
+
end
|
195
230
|
end
|
196
231
|
|
197
|
-
def before(
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
232
|
+
def before(*methods_name, &block)
|
233
|
+
methods_name.each do |method_name|
|
234
|
+
begin
|
235
|
+
method = instance_method method_name
|
236
|
+
|
237
|
+
define_method method_name do |*args|
|
238
|
+
block.call(self,*args)
|
239
|
+
method.bind(self).call(*args)
|
240
|
+
end
|
241
|
+
rescue => e
|
242
|
+
MooseX.warn "unable to apply hook before in #{method_name} @ #{self}: #{e}", caller() if self.is_a?(Class)
|
243
|
+
__meta.add_before(method_name, block)
|
244
|
+
end
|
245
|
+
end
|
208
246
|
end
|
209
247
|
|
210
|
-
def around(
|
211
|
-
|
212
|
-
|
248
|
+
def around(*methods_name, &block)
|
249
|
+
methods_name.each do |method_name|
|
250
|
+
begin
|
251
|
+
method = instance_method method_name
|
213
252
|
|
214
|
-
|
215
|
-
|
216
|
-
|
253
|
+
code = Proc.new do | o, *a|
|
254
|
+
method.bind(o).call(*a)
|
255
|
+
end
|
217
256
|
|
218
|
-
|
257
|
+
define_method method_name do |*args|
|
219
258
|
|
220
|
-
|
259
|
+
block.call(code, self,*args)
|
221
260
|
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
261
|
+
end
|
262
|
+
rescue => e
|
263
|
+
MooseX.warn "unable to apply hook around in #{method_name} @ #{self}: #{e}", caller() if self.is_a?(Class)
|
264
|
+
__meta.add_around(method_name, block)
|
265
|
+
end
|
266
|
+
end
|
226
267
|
end
|
227
268
|
|
228
269
|
def requires(*methods)
|
@@ -416,7 +457,7 @@ module MooseX
|
|
416
457
|
end,
|
417
458
|
};
|
418
459
|
|
419
|
-
def initialize(a, o,
|
460
|
+
def initialize(a, o ,x)
|
420
461
|
#o ||= {}
|
421
462
|
# todo extract this to a framework, see issue #21 on facebook
|
422
463
|
o = DEFAULTS.merge({
|
@@ -470,7 +511,7 @@ module MooseX
|
|
470
511
|
@coerce = o.delete(:coerce)
|
471
512
|
@methods = {}
|
472
513
|
|
473
|
-
warn "
|
514
|
+
MooseX.warn "Unused attributes #{o} for attribute #{a} @ #{x} #{x.class}",caller() if ! o.empty?
|
474
515
|
|
475
516
|
if @reader
|
476
517
|
@methods[@reader] = generate_reader
|
data/lib/moosex/event.rb
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'moosex'
|
2
|
+
require 'moosex/types'
|
3
|
+
|
4
|
+
module MooseX
|
5
|
+
module Event
|
6
|
+
class EventException < StandardError
|
7
|
+
end
|
8
|
+
class EventListener
|
9
|
+
include MooseX
|
10
|
+
|
11
|
+
has once: { is: :rw, reader: :once? }
|
12
|
+
has event: { is: :ro, handles: { :respond_to_event? => :== } }
|
13
|
+
has code: { is: :ro, handles: :call }
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
include MooseX
|
18
|
+
include MooseX::Types
|
19
|
+
|
20
|
+
has listeners: {
|
21
|
+
is: :private,
|
22
|
+
isa: isArray(EventListener),
|
23
|
+
default: lambda{ [] },
|
24
|
+
}
|
25
|
+
|
26
|
+
def has_events
|
27
|
+
nil
|
28
|
+
end
|
29
|
+
|
30
|
+
def on(event, &block)
|
31
|
+
add_event_listener(event, false, block)
|
32
|
+
end
|
33
|
+
|
34
|
+
def once(event, &block)
|
35
|
+
add_event_listener(event, true, block)
|
36
|
+
end
|
37
|
+
|
38
|
+
def emit(event, *args)
|
39
|
+
listeners.select{|l| l.respond_to_event?(event) }.each{|l| l.call(self, *args) }
|
40
|
+
listeners.delete_if {|l| l.once? }
|
41
|
+
end
|
42
|
+
|
43
|
+
def remove_all_listeners(event)
|
44
|
+
listeners.delete_if {|l| l.respond_to_event?(event) }
|
45
|
+
end
|
46
|
+
|
47
|
+
def remove_listener(data)
|
48
|
+
data.each_pair do |event, listener|
|
49
|
+
listeners.delete(listener)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
def add_event_listener(event, once, code)
|
55
|
+
listener = EventListener.new(event: event, once: once, code: code)
|
56
|
+
|
57
|
+
listeners << listener
|
58
|
+
|
59
|
+
listener
|
60
|
+
end
|
61
|
+
|
62
|
+
before(:add_event_listener, :emit) do |obj, event, *rest|
|
63
|
+
|
64
|
+
if ! obj.has_events.nil? && ! [ obj.has_events ].flatten.include?(event)
|
65
|
+
|
66
|
+
raise EventException, "Event '#{event.inspect}' not supported, this class only allow: #{obj.has_events.inspect}",caller
|
67
|
+
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
data/lib/moosex/version.rb
CHANGED
data/spec/event_spec.rb
ADDED
@@ -0,0 +1,164 @@
|
|
1
|
+
require 'moosex'
|
2
|
+
require 'moosex/event'
|
3
|
+
|
4
|
+
class EventExample
|
5
|
+
include MooseX
|
6
|
+
include MooseX::Event
|
7
|
+
|
8
|
+
def has_events
|
9
|
+
[ :pinged, :ponged ]
|
10
|
+
end
|
11
|
+
|
12
|
+
def ping
|
13
|
+
self.emit(:pinged)
|
14
|
+
end
|
15
|
+
|
16
|
+
def pong(message)
|
17
|
+
self.emit(:ponged, message)
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
class EventExample2 < EventExample
|
23
|
+
def has_events; end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe EventExample do
|
27
|
+
it "EventExample should emit ping" do
|
28
|
+
logger = double
|
29
|
+
e = EventExample.new
|
30
|
+
|
31
|
+
logger.should_receive(:on_pinged).with(e).once()
|
32
|
+
e.on(:pinged) do |object|
|
33
|
+
logger.on_pinged(object)
|
34
|
+
end
|
35
|
+
e.ping
|
36
|
+
end
|
37
|
+
|
38
|
+
it "EventExample should emit ping twice, on should receive twice but once will receive once" do
|
39
|
+
logger1 = double
|
40
|
+
logger2 = double
|
41
|
+
|
42
|
+
e = EventExample.new
|
43
|
+
|
44
|
+
logger1.should_receive(:on_pinged).with(e).twice()
|
45
|
+
logger2.should_receive(:on_pinged).with(e).once()
|
46
|
+
|
47
|
+
e.on(:pinged) do |object|
|
48
|
+
logger1.on_pinged(object)
|
49
|
+
end
|
50
|
+
|
51
|
+
e.once(:pinged) do |object|
|
52
|
+
logger2.on_pinged(object)
|
53
|
+
end
|
54
|
+
|
55
|
+
e.ping
|
56
|
+
e.ping
|
57
|
+
end
|
58
|
+
|
59
|
+
it "EventExample should emit ping twice, but you remove all listeners" do
|
60
|
+
logger1 = double
|
61
|
+
logger2 = double
|
62
|
+
|
63
|
+
e = EventExample.new
|
64
|
+
|
65
|
+
logger1.should_receive(:on_pinged).with(e).once()
|
66
|
+
logger2.should_receive(:on_pinged).with(e).once()
|
67
|
+
|
68
|
+
e.on(:pinged) do |object|
|
69
|
+
logger1.on_pinged(object)
|
70
|
+
end
|
71
|
+
|
72
|
+
e.on(:pinged) do |object|
|
73
|
+
logger2.on_pinged(object)
|
74
|
+
end
|
75
|
+
|
76
|
+
e.ping
|
77
|
+
|
78
|
+
e.remove_all_listeners( :pinged )
|
79
|
+
|
80
|
+
e.ping
|
81
|
+
end
|
82
|
+
|
83
|
+
it "EventExample should emit ping twice, but you remove one listener" do
|
84
|
+
logger1 = double
|
85
|
+
logger2 = double
|
86
|
+
|
87
|
+
e = EventExample.new
|
88
|
+
|
89
|
+
logger1.should_receive(:on_pinged).with(e).twice()
|
90
|
+
logger2.should_receive(:on_pinged).with(e).once()
|
91
|
+
|
92
|
+
e.on(:pinged) do |object|
|
93
|
+
logger1.on_pinged(object)
|
94
|
+
end
|
95
|
+
|
96
|
+
listener = e.on(:pinged) do |object|
|
97
|
+
logger2.on_pinged(object)
|
98
|
+
end
|
99
|
+
|
100
|
+
e.ping
|
101
|
+
|
102
|
+
e.remove_listener( pinged: listener )
|
103
|
+
|
104
|
+
e.ping
|
105
|
+
end
|
106
|
+
|
107
|
+
it "should not add listener to a non supported event" do
|
108
|
+
e = EventExample.new
|
109
|
+
expect {
|
110
|
+
e.on(:xxx) {}
|
111
|
+
}.to raise_error(MooseX::Event::EventException,
|
112
|
+
"Event ':xxx' not supported, this class only allow: [:pinged, :ponged]")
|
113
|
+
end
|
114
|
+
|
115
|
+
it "should not add listener to a non supported event" do
|
116
|
+
e = EventExample.new
|
117
|
+
expect {
|
118
|
+
e.once(:xxx) {}
|
119
|
+
}.to raise_error(MooseX::Event::EventException,
|
120
|
+
"Event ':xxx' not supported, this class only allow: [:pinged, :ponged]")
|
121
|
+
end
|
122
|
+
|
123
|
+
it "should not emit a non supported event" do
|
124
|
+
e = EventExample.new
|
125
|
+
expect {
|
126
|
+
e.emit(:xxx)
|
127
|
+
}.to raise_error(MooseX::Event::EventException,
|
128
|
+
"Event ':xxx' not supported, this class only allow: [:pinged, :ponged]")
|
129
|
+
end
|
130
|
+
|
131
|
+
it "should emit ping and pong" do
|
132
|
+
e = EventExample.new
|
133
|
+
logger = double
|
134
|
+
logger.should_receive(:receive_from_ping).with(e,1).once();
|
135
|
+
|
136
|
+
e.once(:pinged) do |obj|
|
137
|
+
obj.pong(1)
|
138
|
+
end
|
139
|
+
e.on(:ponged) do |obj, msg|
|
140
|
+
logger.receive_from_ping(obj, msg)
|
141
|
+
end
|
142
|
+
|
143
|
+
e.ping
|
144
|
+
e.ping
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
describe EventExample2 do
|
149
|
+
it "should not add listener to a non supported event" do
|
150
|
+
e = EventExample2.new
|
151
|
+
e.once(:xxx) {}
|
152
|
+
end
|
153
|
+
|
154
|
+
it "should not emit a non supported event" do
|
155
|
+
e = EventExample2.new
|
156
|
+
|
157
|
+
logger = double
|
158
|
+
logger.should_receive(:called_from_xxx).once()
|
159
|
+
|
160
|
+
e.once(:xxx) { logger.called_from_xxx }
|
161
|
+
|
162
|
+
e.emit(:xxx)
|
163
|
+
end
|
164
|
+
end
|
@@ -0,0 +1,174 @@
|
|
1
|
+
require 'moosex'
|
2
|
+
require 'logger'
|
3
|
+
|
4
|
+
module Logabble
|
5
|
+
include MooseX
|
6
|
+
|
7
|
+
has logger: {
|
8
|
+
is: :ro,
|
9
|
+
#isa: Logger,
|
10
|
+
default: lambda{
|
11
|
+
logger = Logger.new(STDOUT)
|
12
|
+
logger.level = Logger::INFO
|
13
|
+
logger
|
14
|
+
},
|
15
|
+
handles: {
|
16
|
+
log_info: :info,
|
17
|
+
log_warn: :warn,
|
18
|
+
log_fatal: :fatal,
|
19
|
+
log_debug: :debug
|
20
|
+
}
|
21
|
+
}
|
22
|
+
|
23
|
+
on_init do | args |
|
24
|
+
|
25
|
+
klass = args[:klass] || self # this is necessary if you need composable Roles
|
26
|
+
methods = args[:methods] || []
|
27
|
+
|
28
|
+
methods.each do |method|
|
29
|
+
klass.around(method) do |original, object, *args|
|
30
|
+
|
31
|
+
object.log_info([args])
|
32
|
+
|
33
|
+
begin
|
34
|
+
result = original.call(object, *args)
|
35
|
+
|
36
|
+
object.log_warn(result)
|
37
|
+
|
38
|
+
result
|
39
|
+
rescue => e
|
40
|
+
object.log_fatal(e.message)
|
41
|
+
nil
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
module Logabble2
|
52
|
+
include MooseX
|
53
|
+
|
54
|
+
has y: { is: :rw }
|
55
|
+
|
56
|
+
on_init do |args|
|
57
|
+
args[:klass] = self
|
58
|
+
include Logabble.init(args)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
module EasyCrud
|
64
|
+
include MooseX
|
65
|
+
|
66
|
+
on_init do |*attributes|
|
67
|
+
attributes.each do | attr |
|
68
|
+
has attr, { is: :rw, predicate: "has_attr_#{attr}_or_not?" }
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
class LogTest
|
74
|
+
include EasyCrud.init(:a, :b)
|
75
|
+
|
76
|
+
def foo; 1 ; end
|
77
|
+
def bar(a); 1 / a ; end
|
78
|
+
def baz(a,b); 1 + a + b; end
|
79
|
+
|
80
|
+
include Logabble.init(methods: [:foo, :bar, :baz])
|
81
|
+
end
|
82
|
+
|
83
|
+
class LogTest2
|
84
|
+
include MooseX
|
85
|
+
|
86
|
+
def foo; 1 ; end
|
87
|
+
def bar(a); 1 / a ; end
|
88
|
+
def baz(a,b); 1 + a + b; end
|
89
|
+
|
90
|
+
include Logabble2.init(methods: [:foo, :bar, :baz, :y=])
|
91
|
+
end
|
92
|
+
|
93
|
+
describe LogTest do
|
94
|
+
it "should has a logger" do
|
95
|
+
l = LogTest.new()
|
96
|
+
l.logger.is_a?(Logger).should be_true
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should has :a and :b attr" do
|
100
|
+
l = LogTest.new()
|
101
|
+
|
102
|
+
l.has_attr_a_or_not?.should be_false
|
103
|
+
l.has_attr_b_or_not?.should be_false
|
104
|
+
end
|
105
|
+
|
106
|
+
it "should has :a and :b attrs defined" do
|
107
|
+
l = LogTest.new(a: 1, b: 2)
|
108
|
+
|
109
|
+
l.has_attr_a_or_not?.should be_true
|
110
|
+
l.has_attr_b_or_not?.should be_true
|
111
|
+
|
112
|
+
l.a.should == 1
|
113
|
+
l.b.should == 2
|
114
|
+
|
115
|
+
l.a = 5
|
116
|
+
l.b = 6
|
117
|
+
|
118
|
+
l.a.should == 5
|
119
|
+
l.b.should == 6
|
120
|
+
end
|
121
|
+
|
122
|
+
it "call bar(0) should call logger info and fatal" do
|
123
|
+
logger = double
|
124
|
+
logger.should_receive(:info).with([[0]])
|
125
|
+
logger.should_receive(:fatal).with("divided by 0")
|
126
|
+
|
127
|
+
l = LogTest.new(logger: logger)
|
128
|
+
l.bar(0)
|
129
|
+
end
|
130
|
+
|
131
|
+
it "call bar(1) should call logger info and warn" do
|
132
|
+
logger = double
|
133
|
+
logger.should_receive(:info).with([[2]])
|
134
|
+
logger.should_receive(:warn).with(1/2)
|
135
|
+
|
136
|
+
l = LogTest.new(logger: logger)
|
137
|
+
l.bar(2)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
describe LogTest2 do
|
142
|
+
it "should has a logger" do
|
143
|
+
l = LogTest2.new()
|
144
|
+
l.logger.is_a?(Logger).should be_true
|
145
|
+
end
|
146
|
+
|
147
|
+
it "call bar(0) should call logger info and fatal" do
|
148
|
+
logger = double
|
149
|
+
logger.should_receive(:info).with([[0]])
|
150
|
+
logger.should_receive(:fatal).with("divided by 0")
|
151
|
+
|
152
|
+
l = LogTest2.new(logger: logger)
|
153
|
+
l.bar(0)
|
154
|
+
end
|
155
|
+
|
156
|
+
it "call bar(1) should call logger info and warn" do
|
157
|
+
logger = double
|
158
|
+
logger.should_receive(:info).with([[2]])
|
159
|
+
logger.should_receive(:warn).with(1/2)
|
160
|
+
|
161
|
+
l = LogTest2.new(logger: logger)
|
162
|
+
l.bar(2)
|
163
|
+
end
|
164
|
+
|
165
|
+
it "call y= should call logger" do
|
166
|
+
log = double
|
167
|
+
log.should_receive(:info).with([[123]])
|
168
|
+
log.should_receive(:warn).with(123)
|
169
|
+
|
170
|
+
l = LogTest2.new(logger: log)
|
171
|
+
l.y = 123
|
172
|
+
end
|
173
|
+
|
174
|
+
end
|
data/spec/role_spec.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: moosex
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.15
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tiago Peczenyj
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-02-
|
11
|
+
date: 2014-02-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -87,6 +87,7 @@ files:
|
|
87
87
|
- README.md
|
88
88
|
- Rakefile
|
89
89
|
- lib/moosex.rb
|
90
|
+
- lib/moosex/event.rb
|
90
91
|
- lib/moosex/types.rb
|
91
92
|
- lib/moosex/version.rb
|
92
93
|
- moosex.gemspec
|
@@ -98,11 +99,13 @@ files:
|
|
98
99
|
- spec/buildargs_spec.rb
|
99
100
|
- spec/coerce_spec.rb
|
100
101
|
- spec/complex_type_spec.rb
|
102
|
+
- spec/event_spec.rb
|
101
103
|
- spec/foo_spec.rb
|
102
104
|
- spec/hooks_spec.rb
|
103
105
|
- spec/lazy_spec.rb
|
104
106
|
- spec/lol_spec.rb
|
105
107
|
- spec/moosex_spec.rb
|
108
|
+
- spec/parametric_role_spec.rb
|
106
109
|
- spec/point_spec.rb
|
107
110
|
- spec/proxy_spec.rb
|
108
111
|
- spec/role_spec.rb
|
@@ -140,15 +143,16 @@ test_files:
|
|
140
143
|
- spec/buildargs_spec.rb
|
141
144
|
- spec/coerce_spec.rb
|
142
145
|
- spec/complex_type_spec.rb
|
146
|
+
- spec/event_spec.rb
|
143
147
|
- spec/foo_spec.rb
|
144
148
|
- spec/hooks_spec.rb
|
145
149
|
- spec/lazy_spec.rb
|
146
150
|
- spec/lol_spec.rb
|
147
151
|
- spec/moosex_spec.rb
|
152
|
+
- spec/parametric_role_spec.rb
|
148
153
|
- spec/point_spec.rb
|
149
154
|
- spec/proxy_spec.rb
|
150
155
|
- spec/role_spec.rb
|
151
156
|
- spec/spec_helper.rb
|
152
157
|
- spec/trigger_spec.rb
|
153
158
|
- spec/types_spec.rb
|
154
|
-
has_rdoc:
|