bubble-wrap 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +0 -1
- data/.yardopts +2 -0
- data/CHANGELOG.md +15 -0
- data/Gemfile +1 -1
- data/Gemfile.lock +24 -0
- data/HACKING.md +2 -2
- data/README.md +363 -21
- data/Rakefile +6 -2
- data/lib/bubble-wrap.rb +0 -1
- data/lib/bubble-wrap/all.rb +4 -0
- data/lib/bubble-wrap/camera.rb +7 -0
- data/lib/bubble-wrap/core.rb +3 -2
- data/lib/bubble-wrap/ext/motion_project_app.rb +2 -2
- data/lib/bubble-wrap/http.rb +1 -0
- data/lib/bubble-wrap/loader.rb +19 -12
- data/lib/bubble-wrap/location.rb +6 -0
- data/lib/bubble-wrap/reactor.rb +10 -0
- data/lib/bubble-wrap/requirement.rb +11 -3
- data/lib/bubble-wrap/rss_parser.rb +2 -0
- data/lib/bubble-wrap/ui.rb +4 -0
- data/lib/bubble-wrap/version.rb +1 -1
- data/motion/core.rb +8 -2
- data/motion/core/app.rb +34 -6
- data/motion/core/device.rb +10 -1
- data/motion/core/device/camera.rb +219 -0
- data/motion/core/device/camera_wrapper.rb +45 -0
- data/motion/core/ns_url_request.rb +10 -0
- data/motion/core/persistence.rb +7 -0
- data/motion/core/pollute.rb +1 -2
- data/motion/core/string.rb +23 -0
- data/motion/http.rb +142 -83
- data/motion/location/location.rb +152 -0
- data/motion/location/pollute.rb +5 -0
- data/motion/reactor.rb +105 -0
- data/motion/reactor/default_deferrable.rb +9 -0
- data/motion/reactor/deferrable.rb +126 -0
- data/motion/reactor/eventable.rb +24 -0
- data/motion/reactor/future.rb +22 -0
- data/motion/reactor/periodic_timer.rb +27 -0
- data/motion/reactor/queue.rb +60 -0
- data/motion/reactor/timer.rb +25 -0
- data/motion/rss_parser.rb +131 -0
- data/motion/shortcut.rb +18 -0
- data/motion/{core → ui}/gestures.rb +15 -9
- data/motion/ui/pollute.rb +5 -0
- data/motion/{core → ui}/ui_control.rb +0 -0
- data/motion/{core → ui}/ui_view_controller.rb +0 -0
- data/resources/atom.xml +1705 -0
- data/spec/lib/bubble-wrap/ext/motion_project_app_spec.rb +7 -11
- data/spec/lib/bubble-wrap/requirement_spec.rb +4 -4
- data/spec/lib/bubble-wrap_spec.rb +2 -2
- data/spec/motion/core/app_spec.rb +118 -14
- data/spec/motion/core/device/camera_spec.rb +130 -0
- data/spec/motion/core/device/camera_wrapper_spec.rb +45 -0
- data/spec/motion/core/device_spec.rb +0 -50
- data/spec/motion/core/gestures_spec.rb +5 -0
- data/spec/motion/core/persistence_spec.rb +24 -2
- data/spec/motion/core/string_spec.rb +55 -0
- data/spec/motion/core_spec.rb +72 -1
- data/spec/motion/http_spec.rb +100 -65
- data/spec/motion/location/location_spec.rb +152 -0
- data/spec/motion/reactor/eventable_spec.rb +40 -0
- data/spec/motion/reactor_spec.rb +163 -0
- data/spec/motion/rss_parser_spec.rb +36 -0
- metadata +75 -16
data/.gitignore
CHANGED
data/.yardopts
ADDED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,18 @@
|
|
1
|
+
## 1.1.0
|
2
|
+
|
3
|
+
[Commit history](https://github.com/rubymotion/BubbleWrap/compare/1.0...1.1])
|
4
|
+
* Added `BubbleWrap::Reactor`, a simplified implementation of the Event Machine API on top of GCD.
|
5
|
+
* Added upload support to the HTTP wrapper.
|
6
|
+
* Added `BubbleWrap.create_uuid` to generate a uuid string.
|
7
|
+
* Added a program progress proc option to the HTTP wrapper.
|
8
|
+
* Added a RSS parser.
|
9
|
+
* Added a camera wrapper.
|
10
|
+
* Split the various wrappers in self contained and requirable libraries.
|
11
|
+
* Added a wrapper around the location/gps APIs.
|
12
|
+
* Added a merge method to the persistence layer so multiple values can
|
13
|
+
be saved at once.
|
14
|
+
* Added a way to create `UIColor` instances using a hex string: `'#FF8A19'.to_color` or color keyword: `'blue'.to_color`, `'dark_gray'.to_color`.
|
15
|
+
|
1
16
|
## 1.0.0
|
2
17
|
|
3
18
|
* Improved the integration with RubyMotion build system.
|
data/Gemfile
CHANGED
data/Gemfile.lock
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
bubble-wrap (1.1.0)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
bacon (1.1.0)
|
10
|
+
metaclass (0.0.1)
|
11
|
+
mocha (0.12.0)
|
12
|
+
metaclass (~> 0.0.1)
|
13
|
+
mocha-on-bacon (0.2.0)
|
14
|
+
mocha (>= 0.9.8)
|
15
|
+
rake (0.9.2.2)
|
16
|
+
|
17
|
+
PLATFORMS
|
18
|
+
ruby
|
19
|
+
|
20
|
+
DEPENDENCIES
|
21
|
+
bacon
|
22
|
+
bubble-wrap!
|
23
|
+
mocha-on-bacon
|
24
|
+
rake
|
data/HACKING.md
CHANGED
@@ -20,7 +20,7 @@ require 'bubble-wrap'
|
|
20
20
|
When `bubble-wrap` is required it immediately requires `bubble-wrap/loader` which sets up the infrastructure needed to manipulate the `Rakefile` build process. Once that is done we can freely call
|
21
21
|
|
22
22
|
```ruby
|
23
|
-
BubbleWrap.require 'motion/core
|
23
|
+
BubbleWrap.require 'motion/core/**/*.rb'
|
24
24
|
```
|
25
25
|
|
26
26
|
`BubbleWrap.require` (or simply `BW.require`) is used to include
|
@@ -36,7 +36,7 @@ of `BW::Requirement` and thus has access to all it's class methods.
|
|
36
36
|
The most common use cases are setting file dependencies:
|
37
37
|
|
38
38
|
```ruby
|
39
|
-
BW.require('motion/core
|
39
|
+
BW.require('motion/core/**/*.rb') do
|
40
40
|
file('motion/core/device/screen.rb').depends_on 'motion/core/device.rb'
|
41
41
|
end
|
42
42
|
```
|
data/README.md
CHANGED
@@ -13,16 +13,16 @@ gem install bubble-wrap
|
|
13
13
|
|
14
14
|
## Setup
|
15
15
|
|
16
|
-
1. Edit the `Rakefile` of your RubyMotion project and add the following require line
|
16
|
+
1. Edit the `Rakefile` of your RubyMotion project and add the following require line:
|
17
17
|
|
18
18
|
```ruby
|
19
19
|
require 'bubble-wrap'
|
20
20
|
```
|
21
21
|
|
22
22
|
BubbleWrap is split into multiple modules so that you can easily choose which parts
|
23
|
-
are included at compile-time.
|
23
|
+
are included at compile-time.
|
24
24
|
|
25
|
-
The above example requires
|
25
|
+
The above example requires the `core` and `http` modules. If you wish to only
|
26
26
|
include the core modules use the following line of code instead:
|
27
27
|
|
28
28
|
```ruby
|
@@ -35,6 +35,42 @@ If you wish to only include the `HTTP` wrapper:
|
|
35
35
|
require 'bubble-wrap/http'
|
36
36
|
```
|
37
37
|
|
38
|
+
If you wish to only include the `RSS Parser` wrapper:
|
39
|
+
|
40
|
+
```ruby
|
41
|
+
require 'bubble-wrap/rss_parser'
|
42
|
+
```
|
43
|
+
|
44
|
+
If you wish to only include the `Reactor` wrapper:
|
45
|
+
|
46
|
+
```ruby
|
47
|
+
require 'bubble-wrap/reactor'
|
48
|
+
```
|
49
|
+
|
50
|
+
If you wish to only include the UI-related wrappers:
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
require 'bubble-wrap/ui'
|
54
|
+
```
|
55
|
+
|
56
|
+
If you wish to only include the `Camera` wrapper:
|
57
|
+
|
58
|
+
```ruby
|
59
|
+
require 'bubble-wrap/camera'
|
60
|
+
```
|
61
|
+
|
62
|
+
If you wish to only include the `Location` wrapper:
|
63
|
+
|
64
|
+
```ruby
|
65
|
+
require 'bubble-wrap/location'
|
66
|
+
```
|
67
|
+
|
68
|
+
If you want to include everything (ie kitchen sink mode) you can save time and do:
|
69
|
+
|
70
|
+
```ruby
|
71
|
+
require 'bubble-wrap/all'
|
72
|
+
```
|
73
|
+
|
38
74
|
|
39
75
|
Note: **DON'T** use `app.files =` in your Rakefile to set up your files once you've required BubbleWrap.
|
40
76
|
Make sure to append onto the array or use `+=`.
|
@@ -56,6 +92,44 @@ use the versioned gem.
|
|
56
92
|
|
57
93
|
## Core
|
58
94
|
|
95
|
+
### Misc
|
96
|
+
|
97
|
+
UUID generator:
|
98
|
+
```ruby
|
99
|
+
BubbleWrap.create_uuid
|
100
|
+
=> "68ED21DB-82E5-4A56-ABEB-73650C0DB701"
|
101
|
+
```
|
102
|
+
|
103
|
+
Localization (using `NSBundle.mainBundle.localizedStringForKey`):
|
104
|
+
```ruby
|
105
|
+
BubbleWrap.localized_string(:foo, 'fallback')
|
106
|
+
=> "fallback"
|
107
|
+
```
|
108
|
+
|
109
|
+
Color conversion:
|
110
|
+
```ruby
|
111
|
+
BubbleWrap.rgba_color(23, 45, 12, 0.4)
|
112
|
+
=> #<UIDeviceRGBColor:0x6db6ed0>
|
113
|
+
BubbleWrap.rgb_color(23, 45, 12)
|
114
|
+
=> #<UIDeviceRGBColor:0x8ca88b0>
|
115
|
+
'blue'.to_color
|
116
|
+
=> #<UICachedDeviceRGBColor:0xda535c0>
|
117
|
+
'dark_gray'.to_color
|
118
|
+
=> #<UICachedDeviceWhiteColor:0x8bb5be0>
|
119
|
+
'#FF8A19'.to_color
|
120
|
+
=> #<UIDeviceRGBColor:0x8d54110>
|
121
|
+
```
|
122
|
+
|
123
|
+
Debug flag:
|
124
|
+
```ruby
|
125
|
+
BubbleWrap.debug?
|
126
|
+
=> false
|
127
|
+
BubbleWrap.debug = true
|
128
|
+
=> true
|
129
|
+
BubbleWrap.debug?
|
130
|
+
=> true
|
131
|
+
```
|
132
|
+
|
59
133
|
### App
|
60
134
|
|
61
135
|
A module with useful methods related to the running application
|
@@ -73,6 +147,8 @@ A module with useful methods related to the running application
|
|
73
147
|
# creates and shows an alert message.
|
74
148
|
> App.run_after(0.5) { p "It's #{Time.now}" }
|
75
149
|
# Runs the block after 0.5 seconds.
|
150
|
+
> App.open_url("http://matt.aimonetti.net")
|
151
|
+
# Opens the url using the device's browser. (accepts a string url or an instance of `NSURL`.
|
76
152
|
> App::Persistence['channels'] # application specific persistence storage
|
77
153
|
# ['NBC', 'ABC', 'Fox', 'CBS', 'PBS']
|
78
154
|
> App::Persistence['channels'] = ['TF1', 'France 2', 'France 3']
|
@@ -94,6 +170,7 @@ Other available methods:
|
|
94
170
|
A collection of useful methods about the current device:
|
95
171
|
|
96
172
|
Examples:
|
173
|
+
|
97
174
|
```ruby
|
98
175
|
> Device.iphone?
|
99
176
|
# true
|
@@ -119,23 +196,26 @@ Examples:
|
|
119
196
|
# 320
|
120
197
|
```
|
121
198
|
|
122
|
-
###
|
199
|
+
### Camera
|
123
200
|
|
124
|
-
|
201
|
+
Added interface for better camera access:
|
125
202
|
|
126
203
|
```ruby
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
# @view.transform = ...
|
132
|
-
})
|
133
|
-
end
|
134
|
-
```
|
135
|
-
|
136
|
-
There are similar methods for pinched, rotated, swiped, panned, and pressed (for long presses). All of the methods return the actual recognizer object, so it is possible to set the delegate if more fine-grained control is needed.
|
204
|
+
# Uses the front camera
|
205
|
+
BW::Device.camera.front.picture(media_types: [:movie, :image]) do |result|
|
206
|
+
image_view = UIImageView.alloc.initWithImage(result[:original_image])
|
207
|
+
end
|
137
208
|
|
209
|
+
# Uses the rear camera
|
210
|
+
BW::Device.camera.rear.picture(media_types: [:movie, :image]) do |result|
|
211
|
+
image_view = UIImageView.alloc.initWithImage(result[:original_image])
|
212
|
+
end
|
138
213
|
|
214
|
+
# Uses the photo library
|
215
|
+
BW::Device.camera.any.picture(media_types: [:movie, :image]) do |result|
|
216
|
+
image_view = UIImageView.alloc.initWithImage(result[:original_image])
|
217
|
+
end
|
218
|
+
```
|
139
219
|
|
140
220
|
### JSON
|
141
221
|
|
@@ -248,21 +328,51 @@ iso8601 formatted string into a Time instance.
|
|
248
328
|
=> 2012-05-31 21:41:33 +0200
|
249
329
|
```
|
250
330
|
|
251
|
-
|
331
|
+
## Location
|
252
332
|
|
253
|
-
|
333
|
+
Added interface for Ruby-like GPS access:
|
254
334
|
|
255
335
|
```ruby
|
256
|
-
|
257
|
-
|
336
|
+
BW::Location.get do |result|
|
337
|
+
p "From Lat #{result[:from].latitude}, Long #{result[:from].longitude}"
|
338
|
+
p "To Lat #{result[:to].latitude}, Long #{result[:to].longitude}"
|
258
339
|
end
|
259
340
|
```
|
260
341
|
|
342
|
+
Also available is `BW::Location.get_significant`, for monitoring significant location changes.
|
343
|
+
|
344
|
+
## UI
|
345
|
+
|
346
|
+
### Gestures
|
347
|
+
|
348
|
+
Extra methods on `UIView` for working with gesture recognizers. A gesture recognizer can be added using a normal Ruby block, like so:
|
349
|
+
|
350
|
+
```ruby
|
351
|
+
view.whenTapped do
|
352
|
+
UIView.animateWithDuration(1,
|
353
|
+
animations:lambda {
|
354
|
+
# animate
|
355
|
+
# @view.transform = ...
|
356
|
+
})
|
357
|
+
end
|
358
|
+
```
|
359
|
+
|
360
|
+
There are similar methods for pinched, rotated, swiped, panned, and pressed (for long presses). All of the methods return the actual recognizer object, so it is possible to set the delegate if more fine-grained control is needed.
|
361
|
+
|
261
362
|
### UIViewController
|
262
363
|
|
263
364
|
A custom method was added to `UIViewController` to return the content
|
264
365
|
frame of a view controller.
|
265
366
|
|
367
|
+
### UIControl / UIButton
|
368
|
+
|
369
|
+
Helper methods to give `UIButton` a Ruby-like interface. Ex:
|
370
|
+
|
371
|
+
```ruby
|
372
|
+
button.when(UIControlEventTouchUpInside) do
|
373
|
+
self.view.backgroundColor = UIColor.redColor
|
374
|
+
end
|
375
|
+
```
|
266
376
|
|
267
377
|
## HTTP
|
268
378
|
|
@@ -295,16 +405,248 @@ BubbleWrap::HTTP.post("http://foo.bar.com/", {payload: data}) do |response|
|
|
295
405
|
json = BubbleWrap::JSON.parse(response.body.to_str)
|
296
406
|
p json['id']
|
297
407
|
elsif response.status_code.to_s =~ /40\d/
|
298
|
-
alert("Login failed")
|
408
|
+
App.alert("Login failed")
|
299
409
|
else
|
300
|
-
alert(response.error_message)
|
410
|
+
App.alert(response.error_message)
|
301
411
|
end
|
302
412
|
end
|
303
413
|
```
|
304
414
|
|
415
|
+
A `:download_progress` option can also be passed. The expected object
|
416
|
+
would be a Proc that takes two arguments: a float representing the
|
417
|
+
amount of data currently received and another float representing the
|
418
|
+
total amount of data expected.
|
419
|
+
|
420
|
+
|
421
|
+
## RSS Parser
|
422
|
+
**Since: > version 1.0.0**
|
423
|
+
|
424
|
+
The RSS Parser provides an easy interface to consume RSS feeds in an
|
425
|
+
asynchronous (non blocking) way.
|
426
|
+
|
427
|
+
|
428
|
+
```ruby
|
429
|
+
feed_parser = BW::RSSParser.new("http://feeds2.feedburner.com/sdrbpodcast")
|
430
|
+
feed_parser.parse do |item|
|
431
|
+
# called asynchronously as items get parsed
|
432
|
+
p item.title
|
433
|
+
end
|
434
|
+
```
|
435
|
+
|
436
|
+
The yielded RSS item is of type `RSSParser::RSSItem` and has the
|
437
|
+
following attributes:
|
438
|
+
|
439
|
+
* title
|
440
|
+
* description
|
441
|
+
* link
|
442
|
+
* guid
|
443
|
+
* pubDate
|
444
|
+
* enclosure
|
445
|
+
|
446
|
+
The item can be converted into a hash by calling `to_hash` on it.
|
447
|
+
|
448
|
+
### Delegate
|
449
|
+
**Since: > version 1.0.0**
|
450
|
+
|
451
|
+
You can also designate a delegate to the parser and implement change
|
452
|
+
state callbacks:
|
453
|
+
|
454
|
+
```ruby
|
455
|
+
feed_parser = BW::RSSParser.new("http://feeds.feedburner.com/sdrbpodcast")
|
456
|
+
feed_parser.delegate = self
|
457
|
+
feed.parse do |item|
|
458
|
+
p item.title
|
459
|
+
end
|
460
|
+
|
461
|
+
# Delegate method
|
462
|
+
def when_parser_initializes
|
463
|
+
p "The parser is ready!"
|
464
|
+
end
|
465
|
+
|
466
|
+
def when_parser_parses
|
467
|
+
p "The parser started parsing the document"
|
468
|
+
end
|
469
|
+
|
470
|
+
def when_parser_is_done
|
471
|
+
p "The feed is entirely parsed, congratulations!"
|
472
|
+
end
|
473
|
+
```
|
474
|
+
|
475
|
+
These delegate methods are optional, however, you might find the
|
476
|
+
`when_parser_is_done` callback useful if you collected all the items and
|
477
|
+
want to process all at once for instance.
|
478
|
+
|
479
|
+
### Parsing a remote content or actual data
|
480
|
+
|
481
|
+
You have the choice to initialize a parser instance with a string
|
482
|
+
representing an URL, an instance of `NSURL` or my specifying that the
|
483
|
+
passed param is some data to parse directly.
|
484
|
+
|
485
|
+
```ruby
|
486
|
+
# string representing an url:
|
487
|
+
feed_parser = BW::RSSParser.new("http://feeds2.feedburner.com/sdrbpodcast")
|
488
|
+
# a NSURL instance:
|
489
|
+
url = NSURL.alloc.initWithString("http://matt.aimonetti.net/atom.xml")
|
490
|
+
feed_parser = BW::RSSParser.new(url)
|
491
|
+
# Some data
|
492
|
+
feed = File.read('atom.xml')
|
493
|
+
feed_parser = BW::RSSParser.new(feed, true)
|
494
|
+
```
|
495
|
+
|
496
|
+
|
497
|
+
## Reactor
|
498
|
+
**Since: > version 1.0.0**
|
499
|
+
|
500
|
+
`BubbleWrap::Reactor` is a simplified, mostly complete implementation of
|
501
|
+
the [Event Machine](http://rubyeventmachine.com/) API. In fact
|
502
|
+
`BubbleWrap::Reactor` is aliased to `EM` in the runtime environment.
|
503
|
+
|
504
|
+
### Deferables
|
505
|
+
|
506
|
+
BubbleWrap provides both a `Deferrable` mixin and a `DefaultDeferrable`
|
507
|
+
class, which simply mixes in deferrable behaviour if you don't want to
|
508
|
+
implement your own.
|
305
509
|
|
510
|
+
A deferrable is an object with four states: unknown, successful, failure
|
511
|
+
and timeout. When you initially create a deferrable it is in an unknown
|
512
|
+
state, however you can assign callbacks to be run when the object
|
513
|
+
changes to either successful or failure state.
|
514
|
+
|
515
|
+
#### Success
|
516
|
+
|
517
|
+
```ruby
|
518
|
+
> d = EM::DefaultDeferrable.new
|
519
|
+
=> #<BubbleWrap::Reactor::DefaultDeferrable:0x6d859a0>
|
520
|
+
> d.callback { |what| puts "Great #{what}!" }
|
521
|
+
=> [#<Proc:0x6d8a1e0>]
|
522
|
+
> d.succeed "justice"
|
523
|
+
Great justice!
|
524
|
+
=> nil
|
525
|
+
```
|
526
|
+
|
527
|
+
#### Failure
|
528
|
+
|
529
|
+
```ruby
|
530
|
+
> d = EM::DefaultDeferrable.new
|
531
|
+
=> #<BubbleWrap::Reactor::DefaultDeferrable:0x8bf3ee0>
|
532
|
+
> d.errback { |what| puts "Great #{what}!" }
|
533
|
+
=> [#<Proc:0x8bf3ef0>]
|
534
|
+
> d.fail "sadness"
|
535
|
+
Great sadness!
|
536
|
+
=> nil
|
537
|
+
```
|
538
|
+
|
539
|
+
#### Timeout
|
540
|
+
|
541
|
+
```ruby
|
542
|
+
> d = EM::DefaultDeferrable.new
|
543
|
+
=> #<BubbleWrap::Reactor::DefaultDeferrable:0x8bf5910>
|
544
|
+
> d.errback { puts "Great scott!" }
|
545
|
+
=> [#<Proc:0x8bf6350>]
|
546
|
+
> d.timeout 2
|
547
|
+
=> #<BubbleWrap::Reactor::Timer:0x6d920a0 @timer=#<__NSCFTimer:0x6d91990>>
|
548
|
+
# wait...
|
549
|
+
> Great scott!
|
550
|
+
```
|
551
|
+
|
552
|
+
### Timers
|
553
|
+
|
554
|
+
*All timers can be cancelled using `EM.cancel_timer`.*
|
555
|
+
|
556
|
+
#### One-shot timers
|
557
|
+
|
558
|
+
```ruby
|
559
|
+
> EM.add_timer 1.0 do
|
560
|
+
> puts "Great scott!"
|
561
|
+
> end
|
562
|
+
=> 146335904
|
563
|
+
> Great scott!
|
564
|
+
```
|
565
|
+
|
566
|
+
#### Periodic timers
|
567
|
+
|
568
|
+
```ruby
|
569
|
+
> count = 0
|
570
|
+
=> 0
|
571
|
+
> timer = EM.add_periodic_timer 1.0 do
|
572
|
+
> count = count + 1
|
573
|
+
> puts "Great scott!"
|
574
|
+
> (count < 10) || EM.cancel_timer(timer)
|
575
|
+
> end
|
576
|
+
=> 146046832
|
577
|
+
> Great scott!
|
578
|
+
Great scott!
|
579
|
+
Great scott!
|
580
|
+
Great scott!
|
581
|
+
Great scott!
|
582
|
+
Great scott!
|
583
|
+
Great scott!
|
584
|
+
Great scott!
|
585
|
+
Great scott!
|
586
|
+
Great scott!
|
587
|
+
```
|
588
|
+
|
589
|
+
### Scheduling operations
|
590
|
+
|
591
|
+
You can use `EM.schedule` to schedule blocks to be executed
|
592
|
+
asynchronously. BubbleWrap deviates from the EventMachine
|
593
|
+
API here in that it also provides `EM.schedule_on_main` which
|
594
|
+
makes sure that the task is run asynchronously, but on the
|
595
|
+
application's main thread - this is necessary if you are
|
596
|
+
updating the user interface.
|
597
|
+
|
598
|
+
```ruby
|
599
|
+
> EM.schedule { puts Thread.current.object_id }
|
600
|
+
146027920
|
601
|
+
=> nil
|
602
|
+
> EM.schedule_on_main { puts Thread.current.object_id }
|
603
|
+
112222480
|
604
|
+
=> nil
|
605
|
+
```
|
606
|
+
|
607
|
+
### Deferrable operations
|
608
|
+
|
609
|
+
You can also use `EM.defer` in much the same way as `EM.schedule`
|
610
|
+
with one important difference, you can pass in a second `proc`
|
611
|
+
which will be called when the first has completed, and be passed
|
612
|
+
it's result as an argument. Just like `EM.schedule`, `EM.defer`
|
613
|
+
also has an `EM.defer_on_main` version.
|
614
|
+
|
615
|
+
```ruby
|
616
|
+
> operation = proc { 99 }
|
617
|
+
=> #<Proc:0x6d763c0>
|
618
|
+
> callback = proc { |speed| puts speed >= 99 ? "Time travel!" : "Conventional travel!" }
|
619
|
+
=> #<Proc:0x8bd3910>
|
620
|
+
> EM.defer(operation, callback)
|
621
|
+
=> nil
|
622
|
+
Time travel!
|
623
|
+
```
|
624
|
+
|
625
|
+
### Events
|
626
|
+
|
627
|
+
Although not part of the EventMachine API, BubbleWrap provides
|
628
|
+
an `Eventable` mixin for use instrumenting objects with simple
|
629
|
+
event triggering behaviour. `BubbleWrap::Reactor` uses this
|
630
|
+
behind the scenes in several places, and as it's a very handy
|
631
|
+
idiom it is available as a public API.
|
632
|
+
|
633
|
+
```ruby
|
634
|
+
> o = Class.new { include EM::Eventable }.new
|
635
|
+
=> #<#<Class:0x6dc1310>:0x6dc2ec0>
|
636
|
+
> o.on(:november_5_1955) { puts "Ow!" }
|
637
|
+
=> [#<Proc:0x6dc6300>]
|
638
|
+
> o.on(:november_5_1955) { puts "Flux capacitor!" }
|
639
|
+
=> [#<Proc:0x6dc6300>, #<Proc:0x6dc1ba0>]
|
640
|
+
> o.trigger(:november_5_1955)
|
641
|
+
Ow!
|
642
|
+
Flux capacitor!
|
643
|
+
=> [nil, nil]
|
644
|
+
```
|
645
|
+
|
646
|
+
# Suggestions?
|
306
647
|
|
307
648
|
Do you have a suggestion for a specific wrapper? Feel free to open an
|
308
649
|
issue/ticket and tell us about what you are after. If you have a
|
309
650
|
wrapper/helper you are using and are thinking that others might enjoy,
|
310
651
|
please send a pull request (with tests if possible).
|
652
|
+
|