frappuccino 0.2.0 → 0.3.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 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: