frappuccino 0.2.0 → 0.3.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: 3aa6c347af81d9a074803f7be38c360db41adee4
4
- data.tar.gz: 49da3f4765330f9ad73de449aa3080454f9f49e2
3
+ metadata.gz: 0b25e50a7580dd5fd3e7e286b1ad5b5fd3b22f6f
4
+ data.tar.gz: e13f31447678e30538171e18a469c3df4a312a9d
5
5
  SHA512:
6
- metadata.gz: 68c592a44ab4e948adfa4b8bb4214438cf3282cd9a3ce6047c436ad19471fa440b7d9703afc3fd0d9da386cc2873cc9091b7d80abdc8436973df00d0a79b4c40
7
- data.tar.gz: cf1dc7f6d0394e3587714d668ab2a9aa304089ab4c5c239b7bbb8f406818ead40e6aa35dcc6c81c07ee236294090911018531eb3f96aa4484b5a0d902f420a04
6
+ metadata.gz: 7f24114bd056dee3e4948746618e3d7ef73717ba1b9338ef507899dfbd8ef8208a8971006067373911003b484d7e9e1e970b7907fe79e728f19012244b3424a3
7
+ data.tar.gz: 9dc5faa55739df468f2ee0bc67e7bdb0d6bf40a566347d55b679ed2ba7f5333978d8fedeef156afef1ca199301f499686bd0e7b4ffbf11c27d0d8c1f3223040a
@@ -1,8 +1,14 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.0.0
3
+ - 1.9.2
4
4
  - 1.9.3
5
- - rbx-nightly-19mode
5
+ - 2.0.0
6
+ - 2.1.0
6
7
  - jruby-19mode
7
- allow_failures:
8
- - rvm: rbx-nightly-19mode
8
+ - rbx-2
9
+ - ruby-head
10
+ - jruby-head
11
+ matrix:
12
+ allow_failures:
13
+ - rvm: ruby-head
14
+ - rvm: jruby-head
data/README.md CHANGED
@@ -9,22 +9,23 @@ Functional Reactive Programming for Ruby.
9
9
  Add this line to your application's Gemfile:
10
10
 
11
11
  ```ruby
12
- gem 'frappuccino', github: "steveklabnik/frappuccino"
12
+ gem 'frappuccino'
13
13
  ```
14
14
 
15
- (I'm hoping that @yoka will give me the gem name, until then, you
16
- must install from GitHub.)
17
-
18
15
  And then execute:
19
16
 
20
- $ bundle
17
+ ``` sh
18
+ $ bundle
19
+ ```
21
20
 
22
21
  Or install it yourself as:
23
22
 
24
- $ git clone https://github.com/steveklabnik/frappuccino
25
- $ cd frappuccino
26
- $ bundle
27
- $ rake install
23
+ ``` sh
24
+ $ git clone https://github.com/steveklabnik/frappuccino
25
+ $ cd frappuccino
26
+ $ bundle
27
+ $ rake install
28
+ ```
28
29
 
29
30
  ## Usage
30
31
 
@@ -77,7 +78,11 @@ end
77
78
  You can combine two streams together:
78
79
 
79
80
  ```ruby
80
- merged_stream = Frappuccino::Stream.merge(stream_one, stream_two)
81
+ merged_stream = stream_one.merge(stream_two)
82
+
83
+ # or
84
+
85
+ merged_stream = Frappuccino::Stream.merge(one_stream , other_stream)
81
86
 
82
87
  # or
83
88
 
@@ -1,3 +1,19 @@
1
1
  require "frappuccino/version"
2
2
  require "frappuccino/stream"
3
3
  require "frappuccino/property"
4
+
5
+ module Frappuccino
6
+ def self.lift(value)
7
+ Property.new(value)
8
+ end
9
+ end
10
+
11
+ class Object
12
+ def method_missing(method, *args, &block)
13
+ if Frappuccino::Property.method_defined?(method)
14
+ Frappuccino.lift(self).public_send(method, *args, &block)
15
+ else
16
+ super(method, *args, &block)
17
+ end
18
+ end
19
+ end
@@ -1,16 +1,44 @@
1
1
  module Frappuccino
2
2
  class Property
3
- def initialize(zero, stream)
3
+ end
4
+ end
5
+
6
+ require 'frappuccino/property/map_property'
7
+ require 'frappuccino/property/until_property'
8
+ require 'frappuccino/property/toggle_property'
9
+
10
+ module Frappuccino
11
+ class Property
12
+ def initialize(zero, stream = nil)
4
13
  @value = zero
5
- stream.add_observer(self)
14
+
15
+ if stream
16
+ stream.on_value do |value|
17
+ @value = value
18
+ end
19
+ end
6
20
  end
7
21
 
8
22
  def now
9
23
  @value
10
24
  end
11
25
 
12
- def update(value)
13
- @value = value
26
+ def sample(stream)
27
+ stream.map do
28
+ self.now
29
+ end
30
+ end
31
+
32
+ def until(stream, property)
33
+ UntilProperty.new(self, stream, property)
34
+ end
35
+
36
+ def toggle(stream, property)
37
+ ToggleProperty.new(self, stream, property)
38
+ end
39
+
40
+ def map(&blk)
41
+ MapProperty.new(self, &blk)
14
42
  end
15
43
  end
16
44
  end
@@ -0,0 +1,12 @@
1
+ module Frappuccino
2
+ class MapProperty < Property
3
+ def initialize(property, &block)
4
+ @property = property
5
+ @block = block
6
+ end
7
+
8
+ def now
9
+ @block.call(@property.now)
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,16 @@
1
+ module Frappuccino
2
+ class ToggleProperty < Property
3
+ def initialize(first, switcher, second)
4
+ @properties = [first, second]
5
+ @current_index = 0
6
+
7
+ switcher.on_value do
8
+ @current_index = (@current_index + 1) % 2
9
+ end
10
+ end
11
+
12
+ def now
13
+ @properties[@current_index].now
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,17 @@
1
+ module Frappuccino
2
+ class UntilProperty < Property
3
+ def initialize(first, switcher, second)
4
+ @first = first
5
+ @second = second
6
+ @current_prop = @first
7
+
8
+ switcher.on_value do |value|
9
+ @current_prop = @second
10
+ end
11
+ end
12
+
13
+ def now
14
+ @current_prop.now
15
+ end
16
+ end
17
+ end
@@ -90,6 +90,10 @@ module Frappuccino
90
90
  callbacks << blk
91
91
  end
92
92
 
93
+ def merge(another_stream)
94
+ Stream.new(self, another_stream)
95
+ end
96
+
93
97
  def self.merge(stream_one, stream_two)
94
98
  new(stream_one, stream_two)
95
99
  end
@@ -1,3 +1,3 @@
1
1
  module Frappuccino
2
- VERSION = "0.2.0"
2
+ VERSION = "0.3.0"
3
3
  end
@@ -0,0 +1,12 @@
1
+ require 'test_helper'
2
+
3
+ describe "lift" do
4
+ it "returns a Property of the value" do
5
+ prop = Frappuccino.lift("Property")
6
+ assert_equal("Property", prop.now)
7
+ end
8
+
9
+ it "is automatically applied to any Object" do
10
+ assert_equal("Property", "Property".now)
11
+ end
12
+ end
@@ -29,7 +29,7 @@ describe "map" do
29
29
  stream_one = Frappuccino::Stream.new(plus_button)
30
30
  stream_two = Frappuccino::Stream.new(minus_button)
31
31
 
32
- merged_stream = Frappuccino::Stream.merge(stream_one, stream_two)
32
+ merged_stream = stream_one.merge(stream_two)
33
33
  mapped_stream = to_array(merged_stream.map(:+ => 1, :- => -1, :default => 0))
34
34
 
35
35
  assert_equal [], mapped_stream
@@ -48,7 +48,7 @@ describe "map" do
48
48
  stream_one = Frappuccino::Stream.new(plus_button)
49
49
  stream_two = Frappuccino::Stream.new(minus_button)
50
50
 
51
- merged_stream = Frappuccino::Stream.merge(stream_one, stream_two)
51
+ merged_stream = stream_one.merge(stream_two)
52
52
  mapped_stream = to_array(merged_stream.map(:default => 1))
53
53
 
54
54
  assert_equal [], mapped_stream
@@ -7,7 +7,7 @@ describe "merging steams" do
7
7
 
8
8
  stream_one = Frappuccino::Stream.new(button_one)
9
9
  stream_two = Frappuccino::Stream.new(button_two)
10
- merged_stream = to_array(Frappuccino::Stream.merge(stream_one, stream_two))
10
+ merged_stream = to_array(stream_one.merge(stream_two))
11
11
 
12
12
  button_one.push
13
13
  button_two.push
@@ -21,8 +21,7 @@ describe "merging steams" do
21
21
 
22
22
  stream_one = Frappuccino::Stream.new(plus_button)
23
23
  stream_two = Frappuccino::Stream.new(minus_button)
24
-
25
- merged_stream = Frappuccino::Stream.merge(stream_one, stream_two)
24
+ merged_stream = stream_one.merge(stream_two)
26
25
  counter = merged_stream
27
26
  .map do |event|
28
27
  case event
@@ -50,4 +49,33 @@ describe "merging steams" do
50
49
  4.times { plus_button.push }
51
50
  assert_equal 2, counter.now
52
51
  end
52
+
53
+ it "works if the callee has a different constructor from Stream" do
54
+ button_one = Button.new
55
+ button_two = Button.new
56
+
57
+ stream_one = Frappuccino::Stream.new(button_one).map { 0 }
58
+ stream_two = Frappuccino::Stream.new(button_two)
59
+
60
+ # This would explode if the merge was calling
61
+ # self.class.new rather than Stream.new
62
+ stream_one.merge(stream_two)
63
+ end
53
64
  end
65
+
66
+
67
+ describe "merging stream with Frappuccino::Stream#merge" do
68
+ it "produces one stream with both sets of events" do
69
+ button_one = Button.new
70
+ button_two = Button.new
71
+
72
+ stream_one = Frappuccino::Stream.new(button_one)
73
+ stream_two = Frappuccino::Stream.new(button_two)
74
+ merged_stream = to_array(Frappuccino::Stream.merge(stream_one, stream_two))
75
+
76
+ button_one.push
77
+ button_two.push
78
+
79
+ assert_equal 2, merged_stream.length
80
+ end
81
+ end
@@ -10,13 +10,14 @@ describe "MVP interaction" do
10
10
  counter = stream
11
11
  .map {|event| event == :pushed ? 1 : 0 }
12
12
  .inject(0) {|sum, n| sum + n }
13
+ .map { |val| val.to_s }
13
14
 
14
- assert_equal 0, counter.now
15
+ assert_equal "0", counter.now
15
16
 
16
17
  3.times { button.push }
17
- assert_equal 3, counter.now
18
+ assert_equal "3", counter.now
18
19
 
19
20
  button.push
20
- assert_equal 4, counter.now
21
+ assert_equal "4", counter.now
21
22
  end
22
23
  end
@@ -19,4 +19,43 @@ describe "Property" do
19
19
  end
20
20
  end
21
21
  end
22
+
23
+ describe "#sample" do
24
+ before do
25
+ @counter = CounterButton.new(1)
26
+ stream = Frappuccino::Stream.new(@counter)
27
+ prop = Frappuccino::Property.new(0, stream)
28
+
29
+ @sampler = Button.new
30
+ @samples = to_array(prop.sample(Frappuccino::Stream.new(@sampler)))
31
+ end
32
+
33
+ it "has no occurrences initally" do
34
+ assert_equal @samples, []
35
+ end
36
+
37
+ it "samples the Property when the passed Stream occurs" do
38
+ @sampler.push
39
+ assert_equal @samples, [0]
40
+
41
+ @counter.push
42
+ @sampler.push
43
+ assert_equal @samples, [0, 1]
44
+ end
45
+ end
46
+
47
+ describe "#map" do
48
+ it "creates a Property with a mapped value of the original" do
49
+ button = CounterButton.new(1)
50
+ stream = Frappuccino::Stream.new(button)
51
+ prop = Frappuccino::Property.new("0", stream).map do |v|
52
+ v.to_s
53
+ end
54
+
55
+ 5.times do |i|
56
+ assert_equal i.to_s, prop.now
57
+ button.push
58
+ end
59
+ end
60
+ end
22
61
  end
@@ -19,6 +19,10 @@ def to_array(stream)
19
19
  pushed
20
20
  end
21
21
 
22
+ def to_prop(ini, stream)
23
+ Frappuccino::Property.new(ini, stream)
24
+ end
25
+
22
26
  class Button
23
27
  def push
24
28
  emit(:pushed)
@@ -0,0 +1,22 @@
1
+ require 'test_helper'
2
+
3
+ describe "toggle" do
4
+ it "toggles between two Properties on stream occurrences" do
5
+ switch_button = Button.new
6
+ plus_button = PlusOneButton.new
7
+ minus_button = MinusOneButton.new
8
+
9
+ switch = Frappuccino::Stream.new(switch_button)
10
+ plus = to_prop(:+, Frappuccino::Stream.new(plus_button))
11
+ minus = to_prop(:-, Frappuccino::Stream.new(minus_button))
12
+
13
+ prop = plus.toggle(switch, minus)
14
+ assert_equal(:+, prop.now)
15
+
16
+ switch_button.push
17
+ assert_equal(:-, prop.now)
18
+
19
+ switch_button.push
20
+ assert_equal(:+, prop.now)
21
+ end
22
+ end
@@ -0,0 +1,23 @@
1
+ require 'test_helper'
2
+
3
+ describe "until" do
4
+ it "switches the Property on the Stream occurring" do
5
+ switch_button = Button.new
6
+ plus_button = PlusOneButton.new
7
+ minus_button = MinusOneButton.new
8
+
9
+ switch = Frappuccino::Stream.new(switch_button)
10
+ plus = to_prop(:notplus, Frappuccino::Stream.new(plus_button))
11
+ minus = to_prop(:notminus, Frappuccino::Stream.new(minus_button))
12
+
13
+ prop = plus.until(switch, minus)
14
+ assert_equal(:notplus, prop.now)
15
+
16
+ plus_button.push
17
+ assert_equal(:+, prop.now)
18
+
19
+ minus_button.push
20
+ switch_button.push
21
+ assert_equal(:-, prop.now)
22
+ end
23
+ end
@@ -27,7 +27,7 @@ describe "zip" do
27
27
 
28
28
  zipped_stream = to_array(stream1.zip(stream2))
29
29
 
30
- 2.times do |i|
30
+ 2.times do
31
31
  button1.push
32
32
  assert_equal [], zipped_stream, "zipped stream occurred too early"
33
33
  end
@@ -49,7 +49,7 @@ describe "zip" do
49
49
 
50
50
  zipped_stream = to_array(stream1.zip(stream2))
51
51
 
52
- 2.times do |i|
52
+ 2.times do
53
53
  button2.push
54
54
  assert_equal [], zipped_stream, "zipped stream occurred too early"
55
55
  end
metadata CHANGED
@@ -1,41 +1,41 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: frappuccino
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Steve Klabnik
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-06-07 00:00:00.000000000 Z
11
+ date: 2014-08-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ~>
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
19
  version: '1.3'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ~>
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.3'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - '>='
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
33
  version: '0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - '>='
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  description: A library to do Functional Reactive Programming in Ruby.
@@ -45,8 +45,8 @@ executables: []
45
45
  extensions: []
46
46
  extra_rdoc_files: []
47
47
  files:
48
- - .gitignore
49
- - .travis.yml
48
+ - ".gitignore"
49
+ - ".travis.yml"
50
50
  - Gemfile
51
51
  - LICENSE.txt
52
52
  - README.md
@@ -54,6 +54,9 @@ files:
54
54
  - frappuccino.gemspec
55
55
  - lib/frappuccino.rb
56
56
  - lib/frappuccino/property.rb
57
+ - lib/frappuccino/property/map_property.rb
58
+ - lib/frappuccino/property/toggle_property.rb
59
+ - lib/frappuccino/property/until_property.rb
57
60
  - lib/frappuccino/source.rb
58
61
  - lib/frappuccino/stream.rb
59
62
  - lib/frappuccino/stream/drop.rb
@@ -64,6 +67,7 @@ files:
64
67
  - lib/frappuccino/stream/zip.rb
65
68
  - lib/frappuccino/version.rb
66
69
  - test/drop_test.rb
70
+ - test/lift_test.rb
67
71
  - test/map_test.rb
68
72
  - test/merge_test.rb
69
73
  - test/mvp_test.rb
@@ -76,6 +80,8 @@ files:
76
80
  - test/stream_test.rb
77
81
  - test/take_test.rb
78
82
  - test/test_helper.rb
83
+ - test/toggle_test.rb
84
+ - test/until_test.rb
79
85
  - test/zip_test.rb
80
86
  homepage: https://github.com/steveklabnik/frappuccino
81
87
  licenses:
@@ -87,22 +93,23 @@ require_paths:
87
93
  - lib
88
94
  required_ruby_version: !ruby/object:Gem::Requirement
89
95
  requirements:
90
- - - '>='
96
+ - - ">="
91
97
  - !ruby/object:Gem::Version
92
98
  version: '0'
93
99
  required_rubygems_version: !ruby/object:Gem::Requirement
94
100
  requirements:
95
- - - '>='
101
+ - - ">="
96
102
  - !ruby/object:Gem::Version
97
103
  version: '0'
98
104
  requirements: []
99
105
  rubyforge_project:
100
- rubygems_version: 2.0.0
106
+ rubygems_version: 2.2.2
101
107
  signing_key:
102
108
  specification_version: 4
103
109
  summary: Functional Reactive Programming in Ruby.
104
110
  test_files:
105
111
  - test/drop_test.rb
112
+ - test/lift_test.rb
106
113
  - test/map_test.rb
107
114
  - test/merge_test.rb
108
115
  - test/mvp_test.rb
@@ -115,5 +122,6 @@ test_files:
115
122
  - test/stream_test.rb
116
123
  - test/take_test.rb
117
124
  - test/test_helper.rb
125
+ - test/toggle_test.rb
126
+ - test/until_test.rb
118
127
  - test/zip_test.rb
119
- has_rdoc: