reacto 0.0.2 → 0.1.0
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 +4 -4
- data/Gemfile.lock +2 -2
- data/README.md +60 -9
- data/doc/create_and_user_trackables.md +1 -0
- data/lib/reacto.rb +2 -0
- data/lib/reacto/labeled_trackable.rb +13 -0
- data/lib/reacto/operations.rb +4 -0
- data/lib/reacto/operations/concat.rb +1 -1
- data/lib/reacto/operations/depend_on.rb +103 -0
- data/lib/reacto/operations/diff.rb +0 -1
- data/lib/reacto/operations/flat_map.rb +1 -1
- data/lib/reacto/operations/flat_map_latest.rb +3 -4
- data/lib/reacto/operations/label.rb +48 -0
- data/lib/reacto/operations/last.rb +0 -1
- data/lib/reacto/operations/wrap.rb +33 -0
- data/lib/reacto/resources.rb +1 -0
- data/lib/reacto/resources/executor_resource.rb +1 -0
- data/lib/reacto/resources/shared_resource.rb +14 -0
- data/lib/reacto/shared_trackable.rb +56 -0
- data/lib/reacto/subscriptions.rb +6 -0
- data/lib/reacto/subscriptions/flat_map_subscription.rb +6 -1
- data/lib/reacto/subscriptions/inner_subscription.rb +5 -0
- data/lib/reacto/subscriptions/simple_subscription.rb +2 -1
- data/lib/reacto/subscriptions/tracker_subscription.rb +1 -0
- data/lib/reacto/trackable.rb +27 -4
- data/lib/reacto/version.rb +1 -1
- data/spec/reacto/shared_trackable_spec.rb +38 -0
- data/spec/reacto/{create_trackable_spec.rb → trackable/class_level/combine_last_spec.rb} +0 -0
- data/spec/reacto/trackable/class_level/combine_spec.rb +26 -0
- data/spec/reacto/trackable/class_level/interval_spec.rb +13 -2
- data/spec/reacto/trackable/depend_on_spec.rb +70 -0
- data/spec/reacto/trackable/label_spec.rb +40 -0
- data/spec/reacto/trackable/lift_spec.rb +19 -0
- data/spec/reacto/trackable/map_spec.rb +38 -0
- data/spec/reacto/trackable/on_spec.rb +22 -0
- data/spec/reacto/trackable/prepend_spec.rb +15 -0
- data/spec/reacto/trackable/select_spec.rb +26 -0
- data/spec/reacto/{executors_and_trackable_spec.rb → trackable/track_on_spec.rb} +1 -0
- data/spec/reacto/trackable/wrap_spec.rb +46 -0
- metadata +33 -8
- data/spec/reacto/trackable_spec.rb +0 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 98fb0c0ff41e6efde1e6c11574dd9be835684b9d
|
4
|
+
data.tar.gz: b1f541bb712c8add903faa427b739bf8d8846bdd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e8492c6d0751362a31a6b2610ad5ceb16b168adf13ef4be8b53aac834fece5761aed037e334035ec2ed150eb5e6fc2fdefe8eb09da0e23ae2d1c72037b8f5e13
|
7
|
+
data.tar.gz: 4bb888957bb7241ca42c8955d001c5fd32feb3f047b15c01dac0c28c88757dd055139316be71401da0e17318d58829334857980c182d139015284604c2ca4ce0
|
data/Gemfile.lock
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
reacto (0.0
|
4
|
+
reacto (0.1.0)
|
5
5
|
concurrent-ruby (~> 1.0.0)
|
6
6
|
|
7
7
|
GEM
|
8
8
|
remote: https://rubygems.org/
|
9
9
|
specs:
|
10
|
-
concurrent-ruby (1.0.
|
10
|
+
concurrent-ruby (1.0.2)
|
11
11
|
diff-lcs (1.2.5)
|
12
12
|
rspec (3.3.0)
|
13
13
|
rspec-core (~> 3.3.0)
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
#
|
1
|
+
# Reacto
|
2
2
|
|
3
3
|
Reactive Programming for Ruby with some concurrency thrown into the mix!
|
4
4
|
|
@@ -10,7 +10,7 @@ If you use `bundler` just add this line to your `Gemfile`:
|
|
10
10
|
gem 'reacto'
|
11
11
|
```
|
12
12
|
|
13
|
-
Alternatively you can
|
13
|
+
Alternatively you can install the gem with `gem install reacto` or clone this
|
14
14
|
repository and play with it!
|
15
15
|
|
16
16
|
## Why?
|
@@ -18,21 +18,72 @@ repository and play with it!
|
|
18
18
|
Because it is very cool to be reactive these days!
|
19
19
|
Seriously - to be reactive means that your code is able to react on changes
|
20
20
|
happening in various places right away. For example third party data sources or
|
21
|
-
other parts of the code. It helps writing
|
22
|
-
handle failures and still be
|
21
|
+
other parts of the code. It helps writing multi-component apps which could
|
22
|
+
handle failures and still be available.
|
23
23
|
|
24
|
-
Of course there are other
|
24
|
+
Of course there are other implementations of reactive programming for ruby:
|
25
25
|
|
26
|
-
* [RxRuby](https://github.com/ReactiveX/RxRuby) : Very powerful
|
26
|
+
* [RxRuby](https://github.com/ReactiveX/RxRuby) : Very powerful implementation
|
27
27
|
of RX. Handles concurrency and as a whole has more features than `Reacto`.
|
28
28
|
So why `Reacto`? `Reacto` has simpler interface it is native Ruby lib and
|
29
29
|
is easier to use it. The goal of `Reacto` is to be competitor to `RxRuby`
|
30
30
|
in the ruby world.
|
31
|
-
Still the author of
|
31
|
+
Still the author of Reacto is big fan of `RX` especially `RxJava`. He even has
|
32
32
|
a book on the topic using `RxJava` :
|
33
33
|
[Learning Reactive Programming with Java 8](https://www.packtpub.com/application-development/learning-reactive-programming-java-8)
|
34
34
|
* [Frappuccino](https://github.com/steveklabnik/frappuccino) : Very cool lib,
|
35
|
-
easy to use and simply beautiful. The only drawback - it is a bit
|
35
|
+
easy to use and simply beautiful. The only drawback - it is a bit limited :
|
36
36
|
no concurrency and small set of operators.
|
37
37
|
But if you don't need more complicated operators it is the best.
|
38
|
-
The author of `Reacto`
|
38
|
+
The author of `Reacto` highly recommends it.
|
39
|
+
|
40
|
+
## Usage
|
41
|
+
|
42
|
+
### Simple Trackables
|
43
|
+
|
44
|
+
The main entry point to the lib is the `Reacto::Trackable` class.
|
45
|
+
It is something you can track for notifications. Usually A `Reacto::Trackable`
|
46
|
+
implemenation is pushing notifications to some notification tracker.
|
47
|
+
It depends on the source. We can have some remote streaming service as a source,
|
48
|
+
or an synchronous HTTP request or some process pushing updates to another.
|
49
|
+
Of course the source can be very simple, for example a single value:
|
50
|
+
|
51
|
+
```ruby
|
52
|
+
trackable = Reacto::Trackable.value(5)
|
53
|
+
```
|
54
|
+
|
55
|
+
This value won't be emitted as notification until there is no tracker (listener)
|
56
|
+
attached to the `trackable` - so this `trackable` instance is lazy - won't do
|
57
|
+
anything until necessary.
|
58
|
+
|
59
|
+
```ruby
|
60
|
+
trackable.on(value: ->(v) { puts v })
|
61
|
+
|
62
|
+
# => 5
|
63
|
+
```
|
64
|
+
|
65
|
+
This line attaches a notification tracker to the `trackable` - a lambda that
|
66
|
+
should be called when the `trackable` emits any value. This example is very
|
67
|
+
simple and the `trackable` emits only one value - `5` when a tracker is attached
|
68
|
+
to it so the lambda will be called and the value will be printed.
|
69
|
+
|
70
|
+
### Programming Trackable behavior
|
71
|
+
|
72
|
+
A `Reacto::Trackable` can have custom behavior, defining what and when should
|
73
|
+
be sent:
|
74
|
+
|
75
|
+
```ruby
|
76
|
+
trackable = Reacto::Trackable.make do |tracker|
|
77
|
+
tracker.on_value('You say yes')
|
78
|
+
tracker.on_value('I say no')
|
79
|
+
|
80
|
+
sleep 1
|
81
|
+
tracker.on_value('You say stop and I say go go go, oh no')
|
82
|
+
tracker.on_close
|
83
|
+
end
|
84
|
+
```
|
85
|
+
|
86
|
+
When a tracker is attached this behavior will become active and the tracker
|
87
|
+
will receive the first two sentences as values, then, after one second the third
|
88
|
+
one and then a closing notification.
|
89
|
+
|
@@ -0,0 +1 @@
|
|
1
|
+
# Create And Use `Reacto::Trackable` objects.
|
data/lib/reacto.rb
CHANGED
data/lib/reacto/operations.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'reacto/operations/map'
|
2
|
+
require 'reacto/operations/wrap'
|
2
3
|
require 'reacto/operations/select'
|
3
4
|
require 'reacto/operations/inject'
|
4
5
|
require 'reacto/operations/diff'
|
@@ -17,3 +18,6 @@ require 'reacto/operations/throttle'
|
|
17
18
|
require 'reacto/operations/flat_map'
|
18
19
|
require 'reacto/operations/flat_map_latest'
|
19
20
|
require 'reacto/operations/cache'
|
21
|
+
require 'reacto/operations/depend_on'
|
22
|
+
require 'reacto/operations/label'
|
23
|
+
require 'reacto/operations/act'
|
@@ -0,0 +1,103 @@
|
|
1
|
+
require 'reacto/constants'
|
2
|
+
require 'reacto/subscriptions/operation_subscription'
|
3
|
+
|
4
|
+
module Reacto
|
5
|
+
module Operations
|
6
|
+
class DependOn
|
7
|
+
def initialize(trackable, key: :data, accumulator: nil)
|
8
|
+
@key = key
|
9
|
+
@trackable =
|
10
|
+
if accumulator.nil?
|
11
|
+
trackable.first
|
12
|
+
else
|
13
|
+
trackable.inject(NO_VALUE, accumulator)
|
14
|
+
end
|
15
|
+
|
16
|
+
@lock = Mutex.new
|
17
|
+
|
18
|
+
@close = false
|
19
|
+
@error = nil
|
20
|
+
end
|
21
|
+
|
22
|
+
def buffer
|
23
|
+
@buffer ||= []
|
24
|
+
end
|
25
|
+
|
26
|
+
def flush(error = nil)
|
27
|
+
unless error.nil?
|
28
|
+
@tracker.on_error(error)
|
29
|
+
return
|
30
|
+
end
|
31
|
+
|
32
|
+
buffer.each do |val|
|
33
|
+
@tracker.on_value(
|
34
|
+
OpenStruct.new({ value: val }.merge(@key => @result))
|
35
|
+
)
|
36
|
+
end
|
37
|
+
|
38
|
+
@tracker.on_close if @close
|
39
|
+
@tracker.on_error(@error) if @error
|
40
|
+
end
|
41
|
+
|
42
|
+
def check_ready_and_track(tracker)
|
43
|
+
depend_value = ->(v) { @result = v }
|
44
|
+
depend_error = ->(e) { flush(e) }
|
45
|
+
depend_close = -> { flush }
|
46
|
+
|
47
|
+
if @subscription.nil?
|
48
|
+
@tracker = tracker
|
49
|
+
@subscription = @trackable.on(
|
50
|
+
value: depend_value, error: depend_error, close: depend_close
|
51
|
+
)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def call(tracker)
|
56
|
+
value = ->(v) do
|
57
|
+
if @result.nil?
|
58
|
+
@lock.synchronize do
|
59
|
+
buffer << v
|
60
|
+
|
61
|
+
check_ready_and_track(tracker)
|
62
|
+
end
|
63
|
+
else
|
64
|
+
tracker.on_value(
|
65
|
+
OpenStruct.new({ value: v }.merge(@key => @result))
|
66
|
+
)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
error = ->(e) do
|
71
|
+
if @result.nil?
|
72
|
+
@lock.synchronize do
|
73
|
+
@error = e
|
74
|
+
|
75
|
+
check_ready_and_track(tracker)
|
76
|
+
end
|
77
|
+
else
|
78
|
+
tracker.on_error(e)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
close = -> do
|
83
|
+
if @result.nil?
|
84
|
+
@lock.synchronize do
|
85
|
+
@close = true
|
86
|
+
|
87
|
+
check_ready_and_track(tracker)
|
88
|
+
end
|
89
|
+
else
|
90
|
+
tracker.on_close
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
Subscriptions::OperationSubscription.new(
|
95
|
+
tracker,
|
96
|
+
value: value,
|
97
|
+
error: error,
|
98
|
+
close: close
|
99
|
+
)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -13,14 +13,15 @@ module Reacto
|
|
13
13
|
value = lambda do |v|
|
14
14
|
trackable = @transform.call(v)
|
15
15
|
|
16
|
-
sub = subscription.subscription!
|
17
|
-
|
18
16
|
@last_active.unsubscribe if @last_active
|
17
|
+
|
18
|
+
sub = subscription.subscription!
|
19
19
|
trackable.do_track sub
|
20
20
|
@last_active = sub
|
21
21
|
end
|
22
22
|
|
23
23
|
close = lambda do
|
24
|
+
subscription.source_closed = true
|
24
25
|
return unless subscription.closed?
|
25
26
|
|
26
27
|
tracker.on_close
|
@@ -33,5 +34,3 @@ module Reacto
|
|
33
34
|
end
|
34
35
|
end
|
35
36
|
end
|
36
|
-
|
37
|
-
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'reacto/subscriptions/operation_subscription'
|
2
|
+
|
3
|
+
module Reacto
|
4
|
+
module Operations
|
5
|
+
class Label
|
6
|
+
def initialize(chose_label, executor = nil)
|
7
|
+
@chose_label = chose_label
|
8
|
+
@executor = executor
|
9
|
+
|
10
|
+
@labeled_values = {}
|
11
|
+
end
|
12
|
+
|
13
|
+
def call(tracker)
|
14
|
+
value = lambda do |v|
|
15
|
+
label, val = @chose_label.call(v)
|
16
|
+
|
17
|
+
@labeled_values[label] ||= []
|
18
|
+
@labeled_values[label] << val
|
19
|
+
end
|
20
|
+
|
21
|
+
close = lambda do
|
22
|
+
emit_values(tracker)
|
23
|
+
tracker.on_close
|
24
|
+
end
|
25
|
+
|
26
|
+
error = lambda do |err|
|
27
|
+
emit_values(tracker)
|
28
|
+
tracker.on_error(err)
|
29
|
+
end
|
30
|
+
|
31
|
+
Subscriptions::OperationSubscription.new(
|
32
|
+
tracker, value: value, error: error, close: close
|
33
|
+
)
|
34
|
+
end
|
35
|
+
|
36
|
+
def emit_values(tracker)
|
37
|
+
@labeled_values.each do |label, values|
|
38
|
+
trackable =
|
39
|
+
LabeledTrackable.new(label, @executor) do |subscriber|
|
40
|
+
values.each { |val| subscriber.on_value(val) }
|
41
|
+
subscriber.on_close
|
42
|
+
end
|
43
|
+
tracker.on_value(trackable)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
|
3
|
+
require 'reacto/subscriptions/operation_subscription'
|
4
|
+
|
5
|
+
module Reacto
|
6
|
+
module Operations
|
7
|
+
class Wrap
|
8
|
+
def initialize(args)
|
9
|
+
if args.key?(:value)
|
10
|
+
fail ArgumentError, "'value' is not valid key in the wrapping object"
|
11
|
+
end
|
12
|
+
|
13
|
+
if args.key?(:error)
|
14
|
+
fail ArgumentError, "'error' is not valid key in the wrapping object"
|
15
|
+
end
|
16
|
+
|
17
|
+
@args = args
|
18
|
+
end
|
19
|
+
|
20
|
+
def call(tracker)
|
21
|
+
value = ->(v) do
|
22
|
+
data = @args.each_with_object({}) do |(key, val), obj|
|
23
|
+
obj[key] = (val.respond_to? :call) ? val.call(v) : val
|
24
|
+
end
|
25
|
+
|
26
|
+
tracker.on_value OpenStruct.new({ value: v }.merge(data))
|
27
|
+
end
|
28
|
+
|
29
|
+
Subscriptions::OperationSubscription.new(tracker, value: value)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/lib/reacto/resources.rb
CHANGED
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'reacto/trackable'
|
2
|
+
|
3
|
+
module Reacto
|
4
|
+
class SharedTrackable < Trackable
|
5
|
+
def initialize(
|
6
|
+
behaviour = NO_ACTION, executor = nil, activate_on_subscribe = false,
|
7
|
+
&block
|
8
|
+
)
|
9
|
+
super(behaviour, executor, &block)
|
10
|
+
|
11
|
+
@activate_on_subscribe = activate_on_subscribe
|
12
|
+
@active = false
|
13
|
+
end
|
14
|
+
|
15
|
+
def off(notification_tracker = nil)
|
16
|
+
shared_subscription.subscriptions.reject! do |subscription|
|
17
|
+
!subscription.subscribed?
|
18
|
+
end
|
19
|
+
|
20
|
+
return if shared_subscription.subscriptions.count > 0
|
21
|
+
|
22
|
+
shared_subscription.unsubscribe
|
23
|
+
@shared_subscription = nil
|
24
|
+
@active = false
|
25
|
+
end
|
26
|
+
|
27
|
+
def track(notification_tracker)
|
28
|
+
subscription =
|
29
|
+
Subscriptions::TrackerSubscription.new(notification_tracker, self)
|
30
|
+
|
31
|
+
shared_subscription.add(subscription)
|
32
|
+
activate! if @activate_on_subscribe
|
33
|
+
|
34
|
+
Subscriptions::SubscriptionWrapper.new(subscription)
|
35
|
+
end
|
36
|
+
|
37
|
+
def activate!
|
38
|
+
return if @shared_subscription.nil?
|
39
|
+
return if @active
|
40
|
+
|
41
|
+
@active = true
|
42
|
+
do_track(shared_subscription)
|
43
|
+
|
44
|
+
self
|
45
|
+
end
|
46
|
+
|
47
|
+
def activate_on_subscribe
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def shared_subscription
|
53
|
+
@shared_subscription ||= Subscriptions.shared_subscription(self)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
data/lib/reacto/subscriptions.rb
CHANGED
@@ -9,6 +9,8 @@ require 'reacto/subscriptions/combining_last_subscription'
|
|
9
9
|
require 'reacto/subscriptions/zipping_subscription'
|
10
10
|
require 'reacto/subscriptions/flat_map_subscription'
|
11
11
|
|
12
|
+
require 'reacto/resources/shared_resource'
|
13
|
+
|
12
14
|
module Reacto
|
13
15
|
module Subscriptions
|
14
16
|
class << self
|
@@ -22,6 +24,10 @@ module Reacto
|
|
22
24
|
error: -> (_e) { block.call }
|
23
25
|
)
|
24
26
|
end
|
27
|
+
|
28
|
+
def shared_subscription(trackable)
|
29
|
+
SimpleSubscription.new
|
30
|
+
end
|
25
31
|
end
|
26
32
|
end
|
27
33
|
end
|
@@ -4,8 +4,12 @@ require 'reacto/subscriptions/composite_subscription'
|
|
4
4
|
module Reacto
|
5
5
|
module Subscriptions
|
6
6
|
class FlatMapSubscription < CompositeSubscription
|
7
|
+
attr_accessor :source_closed
|
8
|
+
|
7
9
|
def initialize(subscriber)
|
8
10
|
super(nil, subscriber)
|
11
|
+
|
12
|
+
@source_closed = false
|
9
13
|
end
|
10
14
|
|
11
15
|
def waiting?
|
@@ -17,8 +21,9 @@ module Reacto
|
|
17
21
|
end
|
18
22
|
|
19
23
|
def on_close
|
24
|
+
return unless source_closed
|
20
25
|
return unless subscribed?
|
21
|
-
return unless @subscriptions.
|
26
|
+
return unless @subscriptions.all? { |s| s.closed? }
|
22
27
|
|
23
28
|
@subscriber.on_close
|
24
29
|
unsubscribe
|
data/lib/reacto/trackable.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'concurrent'
|
2
|
+
require 'ostruct'
|
2
3
|
|
3
4
|
require 'reacto/constants'
|
4
5
|
require 'reacto/behaviours'
|
@@ -8,6 +9,7 @@ require 'reacto/operations'
|
|
8
9
|
require 'reacto/executors'
|
9
10
|
require 'reacto/resources'
|
10
11
|
|
12
|
+
# TODO: Refactor the constructors and the factory methods
|
11
13
|
module Reacto
|
12
14
|
class Trackable
|
13
15
|
TOPICS = [:open, :value, :error, :close]
|
@@ -89,12 +91,13 @@ module Reacto
|
|
89
91
|
end
|
90
92
|
else
|
91
93
|
make do |tracker|
|
94
|
+
Thread::abort_on_exception = true
|
95
|
+
|
92
96
|
queue = Queue.new
|
93
97
|
task = Concurrent::TimerTask.new(execution_interval: interval) do
|
94
98
|
queue.push('ready')
|
95
99
|
end
|
96
100
|
|
97
|
-
Thread::abort_on_exception = true
|
98
101
|
thread = Thread.new do
|
99
102
|
begin
|
100
103
|
loop do
|
@@ -179,7 +182,7 @@ module Reacto
|
|
179
182
|
track(Tracker.new(trackers))
|
180
183
|
end
|
181
184
|
|
182
|
-
def off(notification_tracker)
|
185
|
+
def off(notification_tracker = nil)
|
183
186
|
# Clean-up logic
|
184
187
|
end
|
185
188
|
|
@@ -194,7 +197,7 @@ module Reacto
|
|
194
197
|
|
195
198
|
def lift(operation = nil, &block)
|
196
199
|
operation = block_given? ? block : operation
|
197
|
-
|
200
|
+
self.class.new(nil, @executor) do |tracker_subscription|
|
198
201
|
begin
|
199
202
|
modified = operation.call(tracker_subscription)
|
200
203
|
lift_behaviour(modified) unless modified == NOTHING
|
@@ -218,6 +221,10 @@ module Reacto
|
|
218
221
|
))
|
219
222
|
end
|
220
223
|
|
224
|
+
def wrap(**args)
|
225
|
+
lift(Operations::Wrap.new(args))
|
226
|
+
end
|
227
|
+
|
221
228
|
def select(filter = nil, &block)
|
222
229
|
lift(Operations::Select.new(block_given? ? block : filter))
|
223
230
|
end
|
@@ -291,12 +298,28 @@ module Reacto
|
|
291
298
|
lift(Operations::Cache.new(type: type, **settings))
|
292
299
|
end
|
293
300
|
|
301
|
+
def depend_on(trackable, key: :data, accumulator: nil, &block)
|
302
|
+
lift(Operations::DependOn.new(
|
303
|
+
trackable, key: key, accumulator: (block_given? ? block : accumulator)
|
304
|
+
))
|
305
|
+
end
|
306
|
+
|
307
|
+
def label(labeling_action = nil, executor: nil, &block)
|
308
|
+
lift(Operations::Label.new(
|
309
|
+
block_given? ? block : labeling_action, executor
|
310
|
+
))
|
311
|
+
end
|
312
|
+
|
313
|
+
def act(action = NO_ACTION, on: Operations::Act::ALL, &block)
|
314
|
+
lift(Operations::Act.new(block_given? ? block : action, on))
|
315
|
+
end
|
316
|
+
|
294
317
|
def track_on(executor)
|
295
318
|
lift(Operations::TrackOn.new(executor))
|
296
319
|
end
|
297
320
|
|
298
321
|
def execute_on(executor)
|
299
|
-
|
322
|
+
self.class.new(@behaviour, executor)
|
300
323
|
end
|
301
324
|
|
302
325
|
def await(subscription, timeout = nil)
|
data/lib/reacto/version.rb
CHANGED
@@ -0,0 +1,38 @@
|
|
1
|
+
context Reacto::SharedTrackable do
|
2
|
+
subject do
|
3
|
+
described_class.interval(0.3).take(10)
|
4
|
+
end
|
5
|
+
|
6
|
+
context '#track' do
|
7
|
+
it 'does not activate the behaviour' do
|
8
|
+
attach_test_trackers(subject)
|
9
|
+
|
10
|
+
sleep 1
|
11
|
+
expect(test_data).to be_empty
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
context '#activate!' do
|
16
|
+
it 'activates the Trackable behavior, all the assigned trackers receive ' \
|
17
|
+
'the same notifications' do
|
18
|
+
attach_test_trackers(subject)
|
19
|
+
|
20
|
+
additional_test_data = []
|
21
|
+
subject.on(value: ->(v) { additional_test_data << v })
|
22
|
+
subject.activate!
|
23
|
+
|
24
|
+
sleep 1
|
25
|
+
expect(test_data).to be == (0..2).to_a
|
26
|
+
expect(additional_test_data).to be == (0..2).to_a
|
27
|
+
|
28
|
+
yet_another_test_data = []
|
29
|
+
subject.on(value: ->(v) { yet_another_test_data << v })
|
30
|
+
|
31
|
+
sleep 1
|
32
|
+
|
33
|
+
expect(test_data).to be == (0..5).to_a
|
34
|
+
expect(additional_test_data).to be == (0..5).to_a
|
35
|
+
expect(yet_another_test_data).to be == (3..5).to_a
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
File without changes
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
context Reacto::Trackable do
|
4
|
+
context '.combine' do
|
5
|
+
it 'combines the notifications of Trackables with different number of ' \
|
6
|
+
'notifications using the passed combinator' do
|
7
|
+
trackable1 = described_class.interval(0.3).take(4)
|
8
|
+
trackable2 = described_class.interval(0.7, ('a'..'b').each)
|
9
|
+
trackable3 = described_class.interval(0.5, ('A'..'C').each)
|
10
|
+
|
11
|
+
trackable = described_class.combine(
|
12
|
+
trackable1, trackable2, trackable3
|
13
|
+
) do |v1, v2, v3|
|
14
|
+
"#{v1} : #{v2} : #{v3}"
|
15
|
+
end
|
16
|
+
|
17
|
+
subscription = attach_test_trackers(trackable)
|
18
|
+
trackable.await(subscription)
|
19
|
+
|
20
|
+
expect(test_data).to be == [
|
21
|
+
'1 : a : A', '2 : a : A', '2 : a : B', '3 : a : B',
|
22
|
+
'3 : b : B', '3 : b : C', '|'
|
23
|
+
]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -3,12 +3,12 @@ require 'spec_helper'
|
|
3
3
|
context Reacto::Trackable do
|
4
4
|
context '.interval' do
|
5
5
|
it 'emits an infinite sequence of number on every n seconds by default' do
|
6
|
-
trackable = described_class.interval(0.
|
6
|
+
trackable = described_class.interval(0.3)
|
7
7
|
subscription = attach_test_trackers(trackable)
|
8
8
|
sleep 1
|
9
9
|
subscription.unsubscribe
|
10
10
|
|
11
|
-
expect(test_data).to be == (0..
|
11
|
+
expect(test_data).to be == (0..2).to_a
|
12
12
|
end
|
13
13
|
|
14
14
|
it 'can use any enumerator to produce the sequence to emit' do
|
@@ -20,6 +20,17 @@ context Reacto::Trackable do
|
|
20
20
|
expect(test_data).to be == ('a'..'i').to_a
|
21
21
|
end
|
22
22
|
|
23
|
+
it 'handles interval of intervals' do
|
24
|
+
trackable = described_class.interval(0.5, (5..5).each)
|
25
|
+
.map { |v| v * 2 }
|
26
|
+
.flat_map { |v| Reacto::Trackable.interval(0.1, (v..15).each) }
|
27
|
+
subscription = attach_test_trackers(trackable)
|
28
|
+
|
29
|
+
trackable.await(subscription)
|
30
|
+
|
31
|
+
expect(test_data).to be == (10..15).to_a + ['|']
|
32
|
+
end
|
33
|
+
|
23
34
|
it 'can use the immediate executor to block the current thread while ' \
|
24
35
|
'emitting' do
|
25
36
|
trackable = described_class.interval(
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
context Reacto::Trackable do
|
4
|
+
context '#depend_on' do
|
5
|
+
it 'suspends its caller untill the passed Trackable emits its ' \
|
6
|
+
'notifications and wraps the value of the caller with the accumulated ' \
|
7
|
+
'data of these notifications' do
|
8
|
+
trackable = described_class.enumerable([1, 5, 4]).depend_on(
|
9
|
+
described_class.value(10)
|
10
|
+
)
|
11
|
+
|
12
|
+
attach_test_trackers(trackable)
|
13
|
+
|
14
|
+
expect(test_data.size).to be 4
|
15
|
+
expect(test_data[0].value).to be 1
|
16
|
+
expect(test_data[0].data).to be 10
|
17
|
+
expect(test_data[1].value).to be 5
|
18
|
+
expect(test_data[1].data).to be 10
|
19
|
+
expect(test_data[2].value).to be 4
|
20
|
+
expect(test_data[2].data).to be 10
|
21
|
+
expect(test_data.last).to be == '|'
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'it uses the first emitted value for the data from the dependency ' \
|
25
|
+
'if no accumulator lambda/block is passed.' do
|
26
|
+
trackable = described_class.enumerable([1, 5, 4]).depend_on(
|
27
|
+
described_class.interval(0.4, [5, 10].each)
|
28
|
+
)
|
29
|
+
|
30
|
+
subscription = attach_test_trackers(trackable)
|
31
|
+
trackable.await(subscription)
|
32
|
+
|
33
|
+
expect(test_data.size).to be 4
|
34
|
+
expect(test_data[0].value).to be 1
|
35
|
+
expect(test_data[0].data).to be 5
|
36
|
+
expect(test_data[1].value).to be 5
|
37
|
+
expect(test_data[1].data).to be 5
|
38
|
+
expect(test_data[2].value).to be 4
|
39
|
+
expect(test_data[2].data).to be 5
|
40
|
+
expect(test_data.last).to be == '|'
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'uses the block passed to accumulate the dependency data' do
|
44
|
+
trackable = described_class.enumerable([5, 4]).depend_on(
|
45
|
+
described_class.enumerable((1..10))
|
46
|
+
) { |prev, v| prev + v }
|
47
|
+
|
48
|
+
attach_test_trackers(trackable)
|
49
|
+
|
50
|
+
expect(test_data.size).to be 3
|
51
|
+
expect(test_data[0].value).to be 5
|
52
|
+
expect(test_data[0].data).to be 55
|
53
|
+
expect(test_data[1].value).to be 4
|
54
|
+
expect(test_data[1].data).to be 55
|
55
|
+
expect(test_data.last).to be == '|'
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'sends the error if the dependency has an error' do
|
59
|
+
error = StandardError.new('Error!')
|
60
|
+
trackable = described_class.enumerable([5, 4]).depend_on(
|
61
|
+
described_class.value(55).concat(described_class.error(error))
|
62
|
+
)
|
63
|
+
|
64
|
+
attach_test_trackers(trackable)
|
65
|
+
|
66
|
+
expect(test_data.size).to be 1
|
67
|
+
expect(test_data.last).to be == error
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
context Reacto::Trackable do
|
2
|
+
context '#label' do
|
3
|
+
it 'transforms each of the values emitted by the source into ' \
|
4
|
+
'LabeledTrackable instances, using the passed function to get their ' \
|
5
|
+
'labels and values to emit' do
|
6
|
+
trackable =
|
7
|
+
Reacto::Trackable.enumerable((1..10).each).label do |value|
|
8
|
+
[(value % 3), value]
|
9
|
+
end
|
10
|
+
|
11
|
+
trackable.on(value: test_on_value)
|
12
|
+
|
13
|
+
expect(test_data.count).to eq(3)
|
14
|
+
|
15
|
+
one = test_data.first
|
16
|
+
expect(one.label).to eq(1)
|
17
|
+
one_array = []
|
18
|
+
one.on(value: ->(v) { one_array << v })
|
19
|
+
expect(one_array).to eq([1, 4, 7, 10])
|
20
|
+
|
21
|
+
two = test_data[1]
|
22
|
+
expect(two.label).to eq(2)
|
23
|
+
two_array = []
|
24
|
+
two.on(value: ->(v) { two_array << v })
|
25
|
+
expect(two_array).to eq([2, 5, 8])
|
26
|
+
|
27
|
+
two = test_data[1]
|
28
|
+
expect(two.label).to eq(2)
|
29
|
+
two_array = []
|
30
|
+
two.on(value: ->(v) { two_array << v })
|
31
|
+
expect(two_array).to eq([2, 5, 8])
|
32
|
+
|
33
|
+
zero = test_data.last
|
34
|
+
expect(zero.label).to eq(0)
|
35
|
+
zero_array = []
|
36
|
+
zero.on(value: ->(v) { zero_array << v })
|
37
|
+
expect(zero_array).to eq([3, 6, 9])
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
context Reacto::Trackable do
|
4
|
+
context '#lift' do
|
5
|
+
it 'applies a transformation to the trackable behaviour' do
|
6
|
+
lifted_trackable = source.lift do |tracker_subscription|
|
7
|
+
Reacto::Subscriptions::OperationSubscription.new(
|
8
|
+
tracker_subscription,
|
9
|
+
value: -> (v) { tracker_subscription.on_value(v * v) }
|
10
|
+
)
|
11
|
+
end
|
12
|
+
|
13
|
+
lifted_trackable.on(value: test_on_value)
|
14
|
+
|
15
|
+
expect(test_data.size).to be(1)
|
16
|
+
expect(test_data[0]).to be(25)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
context Reacto::Trackable do
|
2
|
+
context '#map' do
|
3
|
+
it 'transforms the value of the source Trackable using the passed ' \
|
4
|
+
'transformation' do
|
5
|
+
trackable = source.map do |v|
|
6
|
+
v * v * v
|
7
|
+
end
|
8
|
+
|
9
|
+
trackable.on(value: test_on_value)
|
10
|
+
|
11
|
+
expect(test_data.size).to be(1)
|
12
|
+
expect(test_data[0]).to be(125)
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'transforms errors, if error transformation is passed' do
|
16
|
+
source = described_class.make do |subscriber|
|
17
|
+
subscriber.on_value(4)
|
18
|
+
subscriber.on_error(StandardError.new('error'))
|
19
|
+
end
|
20
|
+
trackable = source.map(-> (v) { v }, error: -> (e) { 5 })
|
21
|
+
|
22
|
+
trackable.on(value: test_on_value, error: test_on_error)
|
23
|
+
|
24
|
+
expect(test_data.size).to be(2)
|
25
|
+
expect(test_data).to be == [4, 5]
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'emits what is produced by the passed `close` function before close' do
|
29
|
+
trackable =
|
30
|
+
described_class.enumerable((1..5)).map(close: ->() { 10 }) do |v|
|
31
|
+
v
|
32
|
+
end
|
33
|
+
|
34
|
+
trackable.on(value: test_on_value, close: test_on_close)
|
35
|
+
expect(test_data).to be == (1..5).to_a + [10, '|']
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
context Reacto::Trackable do
|
4
|
+
context '#on' do
|
5
|
+
it 'returns a Reacto::Subscription' do
|
6
|
+
actual = described_class.new(Reacto::NO_ACTION).on
|
7
|
+
|
8
|
+
expect(actual).to_not be(nil)
|
9
|
+
expect(actual).to be_kind_of(Reacto::Subscriptions::Subscription)
|
10
|
+
end
|
11
|
+
|
12
|
+
context('value') do
|
13
|
+
it 'the trackable behavior uses a subscription which `on_value` ' \
|
14
|
+
'is the passed value action' do
|
15
|
+
described_class.new(test_behaviour).on(value: test_on_value)
|
16
|
+
|
17
|
+
expect(test_data.size).to be(1)
|
18
|
+
expect(test_data[0]).to be(5)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
context Reacto::Trackable do
|
4
|
+
context '#prepend' do
|
5
|
+
it 'emits the passed enumerable before the values, emited by the caller' do
|
6
|
+
source = described_class.enumerable((1..5))
|
7
|
+
trackable = source.prepend((-5..0))
|
8
|
+
|
9
|
+
trackable.on(value: test_on_value)
|
10
|
+
|
11
|
+
expect(test_data.size).to be(11)
|
12
|
+
expect(test_data).to be == (-5..5).to_a
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
context Reacto::Trackable do
|
4
|
+
context '#select' do
|
5
|
+
it 'doesn\'t notify with values not passing the filter block' do
|
6
|
+
trackable = source.select do |v|
|
7
|
+
v % 2 == 0
|
8
|
+
end
|
9
|
+
|
10
|
+
trackable.on(value: test_on_value)
|
11
|
+
|
12
|
+
expect(test_data.size).to be(0)
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'notifies with values passing the filter block' do
|
16
|
+
trackable = source.select do |v|
|
17
|
+
v % 2 == 1
|
18
|
+
end
|
19
|
+
|
20
|
+
trackable.on(value: test_on_value)
|
21
|
+
|
22
|
+
expect(test_data.size).to be(1)
|
23
|
+
expect(test_data[0]).to be(5)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
context Reacto::Trackable do
|
4
|
+
context '#wrap' do
|
5
|
+
it 'wraps the incomming value in object with field `value` - the value' \
|
6
|
+
' and the specified fields' do
|
7
|
+
now = Time.now
|
8
|
+
trackable = described_class.enumerable([1, 2]).wrap(now: now)
|
9
|
+
|
10
|
+
trackable.on(value: test_on_value)
|
11
|
+
|
12
|
+
expect(test_data.size).to be 2
|
13
|
+
expect(test_data.first.value).to be 1
|
14
|
+
expect(test_data.first.now).to be now
|
15
|
+
expect(test_data.last.value).to be 2
|
16
|
+
expect(test_data.last.now).to be now
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'wraps the incomming value in object with field `value` - the value' \
|
20
|
+
' and the specified fields if some of the field values are lambdas, ' \
|
21
|
+
'they are called with passed parameter - the incoming value' do
|
22
|
+
now = Time.now
|
23
|
+
trackable = described_class.enumerable([1, 2]).wrap(
|
24
|
+
now: now, bau: ->(v) { v * 2 }
|
25
|
+
)
|
26
|
+
|
27
|
+
trackable.on(value: test_on_value)
|
28
|
+
|
29
|
+
expect(test_data.size).to be 2
|
30
|
+
expect(test_data.first.value).to be 1
|
31
|
+
expect(test_data.first.now).to be now
|
32
|
+
expect(test_data.first.bau).to be 2
|
33
|
+
expect(test_data.last.value).to be 2
|
34
|
+
expect(test_data.last.now).to be now
|
35
|
+
expect(test_data.last.bau).to be 4
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'raises an ArgumentError if the hash passed has a `value` key' do
|
39
|
+
expect { described_class.enumerable([1, 2]).wrap(value: 4) }.to(
|
40
|
+
raise_error(ArgumentError).with_message(
|
41
|
+
"'value' is not valid key in the wrapping object"
|
42
|
+
)
|
43
|
+
)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: reacto
|
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
|
- Nickolay Tzvetinov - Meddle
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-06-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -64,16 +64,19 @@ files:
|
|
64
64
|
- Gemfile
|
65
65
|
- Gemfile.lock
|
66
66
|
- README.md
|
67
|
+
- doc/create_and_user_trackables.md
|
67
68
|
- lib/reacto.rb
|
68
69
|
- lib/reacto/behaviours.rb
|
69
70
|
- lib/reacto/cache/file.rb
|
70
71
|
- lib/reacto/cache/memory.rb
|
71
72
|
- lib/reacto/constants.rb
|
72
73
|
- lib/reacto/executors.rb
|
74
|
+
- lib/reacto/labeled_trackable.rb
|
73
75
|
- lib/reacto/operations.rb
|
74
76
|
- lib/reacto/operations/buffer.rb
|
75
77
|
- lib/reacto/operations/cache.rb
|
76
78
|
- lib/reacto/operations/concat.rb
|
79
|
+
- lib/reacto/operations/depend_on.rb
|
77
80
|
- lib/reacto/operations/diff.rb
|
78
81
|
- lib/reacto/operations/drop.rb
|
79
82
|
- lib/reacto/operations/drop_errors.rb
|
@@ -81,6 +84,7 @@ files:
|
|
81
84
|
- lib/reacto/operations/flat_map_latest.rb
|
82
85
|
- lib/reacto/operations/flatten.rb
|
83
86
|
- lib/reacto/operations/inject.rb
|
87
|
+
- lib/reacto/operations/label.rb
|
84
88
|
- lib/reacto/operations/last.rb
|
85
89
|
- lib/reacto/operations/map.rb
|
86
90
|
- lib/reacto/operations/merge.rb
|
@@ -90,8 +94,11 @@ files:
|
|
90
94
|
- lib/reacto/operations/throttle.rb
|
91
95
|
- lib/reacto/operations/track_on.rb
|
92
96
|
- lib/reacto/operations/uniq.rb
|
97
|
+
- lib/reacto/operations/wrap.rb
|
93
98
|
- lib/reacto/resources.rb
|
94
99
|
- lib/reacto/resources/executor_resource.rb
|
100
|
+
- lib/reacto/resources/shared_resource.rb
|
101
|
+
- lib/reacto/shared_trackable.rb
|
95
102
|
- lib/reacto/subscriptions.rb
|
96
103
|
- lib/reacto/subscriptions/buffered_subscription.rb
|
97
104
|
- lib/reacto/subscriptions/combining_last_subscription.rb
|
@@ -110,11 +117,12 @@ files:
|
|
110
117
|
- lib/reacto/tracker.rb
|
111
118
|
- lib/reacto/version.rb
|
112
119
|
- reacto.gemspec
|
113
|
-
- spec/reacto/create_trackable_spec.rb
|
114
|
-
- spec/reacto/executors_and_trackable_spec.rb
|
115
120
|
- spec/reacto/operations/track_on_spec.rb
|
121
|
+
- spec/reacto/shared_trackable_spec.rb
|
116
122
|
- spec/reacto/trackable/buffer_spec.rb
|
117
123
|
- spec/reacto/trackable/cache_spec.rb
|
124
|
+
- spec/reacto/trackable/class_level/combine_last_spec.rb
|
125
|
+
- spec/reacto/trackable/class_level/combine_spec.rb
|
118
126
|
- spec/reacto/trackable/class_level/enumerable_spec.rb
|
119
127
|
- spec/reacto/trackable/class_level/error_spec.rb
|
120
128
|
- spec/reacto/trackable/class_level/interval_spec.rb
|
@@ -123,18 +131,26 @@ files:
|
|
123
131
|
- spec/reacto/trackable/class_level/never_spec.rb
|
124
132
|
- spec/reacto/trackable/class_level/value_spec.rb
|
125
133
|
- spec/reacto/trackable/concat_spec.rb
|
134
|
+
- spec/reacto/trackable/depend_on_spec.rb
|
126
135
|
- spec/reacto/trackable/diff_spec.rb
|
127
136
|
- spec/reacto/trackable/drop_errors_spec.rb
|
128
137
|
- spec/reacto/trackable/flat_map_latest_spec.rb
|
129
138
|
- spec/reacto/trackable/flat_map_spec.rb
|
130
139
|
- spec/reacto/trackable/flatten_spec.rb
|
131
140
|
- spec/reacto/trackable/inject_spec.rb
|
141
|
+
- spec/reacto/trackable/label_spec.rb
|
142
|
+
- spec/reacto/trackable/lift_spec.rb
|
143
|
+
- spec/reacto/trackable/map_spec.rb
|
132
144
|
- spec/reacto/trackable/merge_spec.rb
|
145
|
+
- spec/reacto/trackable/on_spec.rb
|
133
146
|
- spec/reacto/trackable/positional_filtering_spec.rb
|
147
|
+
- spec/reacto/trackable/prepend_spec.rb
|
148
|
+
- spec/reacto/trackable/select_spec.rb
|
134
149
|
- spec/reacto/trackable/throttle_spec.rb
|
150
|
+
- spec/reacto/trackable/track_on_spec.rb
|
135
151
|
- spec/reacto/trackable/uniq_spec.rb
|
152
|
+
- spec/reacto/trackable/wrap_spec.rb
|
136
153
|
- spec/reacto/trackable/zip_spec.rb
|
137
|
-
- spec/reacto/trackable_spec.rb
|
138
154
|
- spec/spec_helper.rb
|
139
155
|
- spec/support/helpers.rb
|
140
156
|
homepage: https://github.com/meddle0x53/reacto
|
@@ -162,11 +178,12 @@ signing_key:
|
|
162
178
|
specification_version: 4
|
163
179
|
summary: Concurrent Reactive Programming for Ruby
|
164
180
|
test_files:
|
165
|
-
- spec/reacto/create_trackable_spec.rb
|
166
|
-
- spec/reacto/executors_and_trackable_spec.rb
|
167
181
|
- spec/reacto/operations/track_on_spec.rb
|
182
|
+
- spec/reacto/shared_trackable_spec.rb
|
168
183
|
- spec/reacto/trackable/buffer_spec.rb
|
169
184
|
- spec/reacto/trackable/cache_spec.rb
|
185
|
+
- spec/reacto/trackable/class_level/combine_last_spec.rb
|
186
|
+
- spec/reacto/trackable/class_level/combine_spec.rb
|
170
187
|
- spec/reacto/trackable/class_level/enumerable_spec.rb
|
171
188
|
- spec/reacto/trackable/class_level/error_spec.rb
|
172
189
|
- spec/reacto/trackable/class_level/interval_spec.rb
|
@@ -175,17 +192,25 @@ test_files:
|
|
175
192
|
- spec/reacto/trackable/class_level/never_spec.rb
|
176
193
|
- spec/reacto/trackable/class_level/value_spec.rb
|
177
194
|
- spec/reacto/trackable/concat_spec.rb
|
195
|
+
- spec/reacto/trackable/depend_on_spec.rb
|
178
196
|
- spec/reacto/trackable/diff_spec.rb
|
179
197
|
- spec/reacto/trackable/drop_errors_spec.rb
|
180
198
|
- spec/reacto/trackable/flat_map_latest_spec.rb
|
181
199
|
- spec/reacto/trackable/flat_map_spec.rb
|
182
200
|
- spec/reacto/trackable/flatten_spec.rb
|
183
201
|
- spec/reacto/trackable/inject_spec.rb
|
202
|
+
- spec/reacto/trackable/label_spec.rb
|
203
|
+
- spec/reacto/trackable/lift_spec.rb
|
204
|
+
- spec/reacto/trackable/map_spec.rb
|
184
205
|
- spec/reacto/trackable/merge_spec.rb
|
206
|
+
- spec/reacto/trackable/on_spec.rb
|
185
207
|
- spec/reacto/trackable/positional_filtering_spec.rb
|
208
|
+
- spec/reacto/trackable/prepend_spec.rb
|
209
|
+
- spec/reacto/trackable/select_spec.rb
|
186
210
|
- spec/reacto/trackable/throttle_spec.rb
|
211
|
+
- spec/reacto/trackable/track_on_spec.rb
|
187
212
|
- spec/reacto/trackable/uniq_spec.rb
|
213
|
+
- spec/reacto/trackable/wrap_spec.rb
|
188
214
|
- spec/reacto/trackable/zip_spec.rb
|
189
|
-
- spec/reacto/trackable_spec.rb
|
190
215
|
- spec/spec_helper.rb
|
191
216
|
- spec/support/helpers.rb
|
@@ -1,16 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
context Reacto::Trackable do
|
4
|
-
context '.new' do
|
5
|
-
it 'supports behavior invoked on tracking, passed as block' do
|
6
|
-
trackable = described_class.new do |tracker_subscription|
|
7
|
-
tracker_subscription.on_value(4)
|
8
|
-
tracker_subscription.on_close
|
9
|
-
end
|
10
|
-
|
11
|
-
trackable.on(value: test_on_value)
|
12
|
-
expect(test_data.size).to be(1)
|
13
|
-
expect(test_data[0]).to be(4)
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|