promise.rb 0.2.1 → 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.
data/.travis.yml CHANGED
@@ -3,11 +3,11 @@ rvm:
3
3
  - 1.9.3
4
4
  - 2.0.0
5
5
  - jruby-19mode
6
- - rbx-19mode
6
+ - rbx
7
7
  - ruby-head
8
8
  - jruby-head
9
9
  matrix:
10
10
  allow_failures:
11
11
  - rvm: ruby-head
12
12
  - rvm: jruby-head
13
- script: bundle exec rake ci:metrics -t
13
+ script: bundle exec rake -t metrics:coverage ci
data/Gemfile CHANGED
@@ -9,5 +9,12 @@ gem 'fuubar', git: 'https://github.com/lgierth/fuubar.git',
9
9
  ref: 'static-percentage'
10
10
  gem 'awesome_print'
11
11
 
12
+ platform :rbx do
13
+ gem 'rubysl', '~> 2.0'
14
+ gem 'rubysl-json', '~> 2.0'
15
+ gem 'rubinius', '~> 2.0'
16
+ gem 'racc'
17
+ end
18
+
12
19
  # Added by devtools
13
20
  eval_gemfile 'Gemfile.devtools'
data/README.md CHANGED
@@ -1,4 +1,90 @@
1
- promise
2
- =======
1
+ # promise.rb [![Build Status](https://travis-ci.org/lgierth/promise.rb.png?branch=master)](https://travis-ci.org/lgierth/promise.rb) [![Code Climate](https://codeclimate.com/github/lgierth/promise.rb.png)](https://codeclimate.com/github/lgierth/promise.rb) [![Coverage Status](https://coveralls.io/repos/lgierth/promise.rb/badge.png?branch=master)](https://coveralls.io/r/lgierth/promise.rb?branch=master)
3
2
 
4
- Promises/A+ for Ruby
3
+ Ruby implementation of the [Promises/A+ spec](http://promisesaplus.com/).
4
+ 100% mutation coverage, tested on 1.9, 2.0, Rubinius, and JRuby.
5
+
6
+ ## Installation
7
+
8
+ Add this line to your application's Gemfile:
9
+
10
+ gem 'promise.rb'
11
+
12
+ And then execute:
13
+
14
+ $ bundle
15
+
16
+ Or install it yourself as:
17
+
18
+ $ gem install promise.rb
19
+
20
+ ## Usage
21
+
22
+ promise.rb doesn't come with a way of scheduling callback dispatch.
23
+
24
+ ```ruby
25
+ require 'promise'
26
+
27
+ class MyPromise < Promise
28
+ def defer(callback, arg)
29
+ callback.dispatch(arg)
30
+ end
31
+ end
32
+ ```
33
+
34
+ The above scheduling mechanism violates the following section of the spec:
35
+
36
+ > onFulfilled or onRejected must not be called until the execution context
37
+ > stack contains only platform code.
38
+
39
+ Compliance can be achieved, for example, by running an event reactor like
40
+ EventMachine:
41
+
42
+ ```ruby
43
+ require 'promise'
44
+ require 'eventmachine'
45
+
46
+ class MyPromise < Promise
47
+ def defer(callback, arg)
48
+ EM.next_tick { callback.dispatch(arg) }
49
+ end
50
+ end
51
+ ```
52
+
53
+ Now you can create MyPromise objects, and fullfil (or reject) them, as well as
54
+ add callbacks to them:
55
+
56
+ ```ruby
57
+ def nonblocking_stuff
58
+ promise = MyPromise.new
59
+ EM.next_tick { promise.fulfill('value') }
60
+ promise
61
+ end
62
+
63
+ nonblocking_stuff.then { |value| p value }
64
+ nonblocking_stuff.then(proc { |value| p value })
65
+ ```
66
+
67
+ Rejection works similarly:
68
+
69
+ ```ruby
70
+ def failing_stuff
71
+ promise = MyPromise.new
72
+ EM.next_tick { promise.reject('reason') }
73
+ promise
74
+ end
75
+
76
+ failing_stuff.then(proc { |value| }, proc { |reason| p reason })
77
+ ```
78
+
79
+ ## License
80
+
81
+ Hatetepe is licensed under the [MIT License](http://opensource.org/licenses/MIT).
82
+ See LICENSE.txt for details.
83
+
84
+ ## Contributing
85
+
86
+ 1. Fork it
87
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
88
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
89
+ 4. Push to the branch (`git push origin my-new-feature`)
90
+ 5. Create new Pull Request
data/config/flay.yml CHANGED
@@ -1,3 +1,3 @@
1
1
  ---
2
- threshold: 12
2
+ threshold: 14
3
3
  total_score: 49
data/config/reek.yml CHANGED
@@ -57,7 +57,7 @@ TooManyInstanceVariables:
57
57
  TooManyMethods:
58
58
  enabled: true
59
59
  exclude: []
60
- max_methods: 11
60
+ max_methods: 13
61
61
  TooManyStatements:
62
62
  enabled: true
63
63
  exclude:
data/lib/promise.rb CHANGED
@@ -34,14 +34,20 @@ class Promise
34
34
  next_promise
35
35
  end
36
36
 
37
- def fulfill(value)
37
+ def sync
38
+ wait if pending?
39
+ fail reason if rejected?
40
+ value
41
+ end
42
+
43
+ def fulfill(value = nil)
38
44
  dispatch(@on_fulfill, value) do
39
45
  @state = :fulfilled
40
46
  @value = value
41
47
  end
42
48
  end
43
49
 
44
- def reject(reason)
50
+ def reject(reason = nil)
45
51
  dispatch(@on_reject, reason) do
46
52
  @state = :rejected
47
53
  @reason = reason
@@ -61,7 +67,7 @@ class Promise
61
67
  if pending?
62
68
  yield
63
69
  arg.freeze
64
- callbacks.each { |callback| defer(callback, arg) }
70
+ callbacks.each { |callback| dispatch!(callback, arg) }
65
71
  end
66
72
 
67
73
  # Callback#assume_state uses #dispatch as returned_promise's on_fulfill
@@ -74,15 +80,19 @@ class Promise
74
80
 
75
81
  def maybe_dispatch(fulfill_callback, reject_callback)
76
82
  if fulfilled?
77
- defer(fulfill_callback, value)
83
+ dispatch!(fulfill_callback, value)
78
84
  end
79
85
 
80
86
  if rejected?
81
- defer(reject_callback, reason)
87
+ dispatch!(reject_callback, reason)
82
88
  end
83
89
  end
84
90
 
85
- def defer(callback, arg)
86
- callback.dispatch(arg)
91
+ def dispatch!(callback, arg)
92
+ defer { callback.dispatch(arg) }
93
+ end
94
+
95
+ def defer
96
+ yield
87
97
  end
88
98
  end
@@ -1,5 +1,5 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  class Promise
4
- VERSION = '0.2.1'
4
+ VERSION = '0.3.0'
5
5
  end
data/spec/promise_spec.rb CHANGED
@@ -7,8 +7,12 @@ describe Promise do
7
7
 
8
8
  let(:value) { double('value') }
9
9
  let(:other_value) { double('other_value') }
10
- let(:reason) { double('reason') }
11
- let(:other_reason) { double('other_reason') }
10
+ let(:reason) do
11
+ StandardError.new('reason').tap { |ex| ex.set_backtrace(caller) }
12
+ end
13
+ let(:other_reason) do
14
+ StandardError.new('other_reason').tap { |ex| ex.set_backtrace(caller) }
15
+ end
12
16
 
13
17
  describe '3.1.1 pending' do
14
18
  it 'transitions to fulfilled' do
@@ -337,11 +341,39 @@ describe Promise do
337
341
  it 'does not return anything' do
338
342
  expect(subject.fulfill(nil)).to eq(nil)
339
343
  end
344
+
345
+ it 'does not require a value' do
346
+ subject.fulfill
347
+ expect(subject.value).to be(nil)
348
+ end
340
349
  end
341
350
 
342
351
  describe '#reject' do
343
352
  it 'does not return anything' do
344
353
  expect(subject.reject(nil)).to eq(nil)
345
354
  end
355
+
356
+ it 'does not require a reason' do
357
+ subject.reject
358
+ expect(subject.reason).to be(nil)
359
+ end
360
+ end
361
+
362
+ describe '#sync' do
363
+ it 'waits for fulfillment' do
364
+ allow(subject).to receive(:wait) { subject.fulfill(value) }
365
+ expect(subject.sync).to be(value)
366
+ end
367
+
368
+ it 'waits for rejection' do
369
+ allow(subject).to receive(:wait) { subject.reject(reason) }
370
+ expect { subject.sync }.to raise_error(reason)
371
+ end
372
+
373
+ it 'waits if pending' do
374
+ subject.fulfill(value)
375
+ expect(subject).not_to receive(:wait)
376
+ expect(subject.sync).to be(value)
377
+ end
346
378
  end
347
379
  end
metadata CHANGED
@@ -1,18 +1,20 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: promise.rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
+ prerelease:
5
6
  platform: ruby
6
7
  authors:
7
8
  - Lars Gierth
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2013-10-19 00:00:00.000000000 Z
12
+ date: 2013-12-07 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
15
  name: rspec
15
16
  requirement: !ruby/object:Gem::Requirement
17
+ none: false
16
18
  requirements:
17
19
  - - ! '>='
18
20
  - !ruby/object:Gem::Version
@@ -20,6 +22,7 @@ dependencies:
20
22
  type: :development
21
23
  prerelease: false
22
24
  version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
23
26
  requirements:
24
27
  - - ! '>='
25
28
  - !ruby/object:Gem::Version
@@ -56,26 +59,27 @@ files:
56
59
  homepage: https://github.com/lgierth/promise
57
60
  licenses:
58
61
  - MIT
59
- metadata: {}
60
62
  post_install_message:
61
63
  rdoc_options: []
62
64
  require_paths:
63
65
  - lib
64
66
  required_ruby_version: !ruby/object:Gem::Requirement
67
+ none: false
65
68
  requirements:
66
69
  - - ! '>='
67
70
  - !ruby/object:Gem::Version
68
71
  version: '0'
69
72
  required_rubygems_version: !ruby/object:Gem::Requirement
73
+ none: false
70
74
  requirements:
71
75
  - - ! '>='
72
76
  - !ruby/object:Gem::Version
73
77
  version: '0'
74
78
  requirements: []
75
79
  rubyforge_project:
76
- rubygems_version: 2.1.5
80
+ rubygems_version: 1.8.23
77
81
  signing_key:
78
- specification_version: 4
82
+ specification_version: 3
79
83
  summary: Promises/A+ for Ruby
80
84
  test_files:
81
85
  - spec/promise_spec.rb
checksums.yaml DELETED
@@ -1,15 +0,0 @@
1
- ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- NGFmYWVmYmRmNWEyMjkyYmMwY2Y0NjA2OWE1YzBjZTM2NTlkNzFmMA==
5
- data.tar.gz: !binary |-
6
- ODg2NzU0ZjFmZTZjY2YzODFlYzJiYzUwMWE1OGQ2NWE4MGVlYTM0ZQ==
7
- SHA512:
8
- metadata.gz: !binary |-
9
- NzA4MmZhMGJiNTliYWIxZjQ5NmY1YTc2NTE5ZTQzY2Y1MTEzNzEyZGVjY2Yy
10
- MjdkODk5ZGYxMjMwMjZiYjUzODdmZmY2YzIxNDk1M2Y3ZWQ1M2RkMjdhY2Jl
11
- MTRhNzY2M2E4NWExNjY1OTg3OTYzYmI2NzY0MzZlNDE3ZmI2YWY=
12
- data.tar.gz: !binary |-
13
- N2MxOTAzZWMzMmUyNGY4MTVhODEwZWYwODNhNmRkYmMwYjU1MWNjNTI3ZGQz
14
- MTZhZDliZWQyZWRjNmVkN2E4MDA5YzhhZjBmMDkxMTYxNTQzYTRkZWU3N2Ix
15
- MTgyZGMyZTNiMjJiMTczZDRmNTA4ZjEzMDE2MDZhMjc4YmI4ZWY=