rubymotion-observer 0.0.1
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/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/Rakefile +1 -0
- data/lib/observer/observer.rb +192 -0
- data/lib/observer/version.rb +3 -0
- data/lib/rubymotion-observer.rb +24 -0
- data/rubymotion-observer.gemspec +16 -0
- metadata +54 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Michael Erasmus
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# RubyMotionObserver
|
2
|
+
This provides a RubyMotion compatible implementation of the ruby stdlib Observable library.
|
3
|
+
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'rubymotion-observer'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install rubymotion-observer
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
This works in exactly the same manner as the [standard Ruby implementation](http://www.ruby-doc.org/stdlib-1.9.3/libdoc/observer/rdoc/Observable.html).
|
22
|
+
|
23
|
+
## Contributing
|
24
|
+
|
25
|
+
1. Fork it
|
26
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
28
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,192 @@
|
|
1
|
+
#
|
2
|
+
# observer.rb implements the _Observer_ object-oriented design pattern. The
|
3
|
+
# following documentation is copied, with modifications, from "Programming
|
4
|
+
# Ruby", by Hunt and Thomas; http://www.rubycentral.com/book/lib_patterns.html.
|
5
|
+
#
|
6
|
+
# == About
|
7
|
+
#
|
8
|
+
# The Observer pattern, also known as Publish/Subscribe, provides a simple
|
9
|
+
# mechanism for one object to inform a set of interested third-party objects
|
10
|
+
# when its state changes.
|
11
|
+
#
|
12
|
+
# == Mechanism
|
13
|
+
#
|
14
|
+
# In the Ruby implementation, the notifying class mixes in the +Observable+
|
15
|
+
# module, which provides the methods for managing the associated observer
|
16
|
+
# objects.
|
17
|
+
#
|
18
|
+
# The observers must implement the +update+ method to receive notifications.
|
19
|
+
#
|
20
|
+
# The observable object must:
|
21
|
+
# * assert that it has +changed+
|
22
|
+
# * call +notify_observers+
|
23
|
+
#
|
24
|
+
# == Example
|
25
|
+
#
|
26
|
+
# The following example demonstrates this nicely. A +Ticker+, when run,
|
27
|
+
# continually receives the stock +Price+ for its +@symbol+. A +Warner+ is a
|
28
|
+
# general observer of the price, and two warners are demonstrated, a +WarnLow+
|
29
|
+
# and a +WarnHigh+, which print a warning if the price is below or above their
|
30
|
+
# set limits, respectively.
|
31
|
+
#
|
32
|
+
# The +update+ callback allows the warners to run without being explicitly
|
33
|
+
# called. The system is set up with the +Ticker+ and several observers, and the
|
34
|
+
# observers do their duty without the top-level code having to interfere.
|
35
|
+
#
|
36
|
+
# Note that the contract between publisher and subscriber (observable and
|
37
|
+
# observer) is not declared or enforced. The +Ticker+ publishes a time and a
|
38
|
+
# price, and the warners receive that. But if you don't ensure that your
|
39
|
+
# contracts are correct, nothing else can warn you.
|
40
|
+
#
|
41
|
+
# require "observer"
|
42
|
+
#
|
43
|
+
# class Ticker ### Periodically fetch a stock price.
|
44
|
+
# include Observable
|
45
|
+
#
|
46
|
+
# def initialize(symbol)
|
47
|
+
# @symbol = symbol
|
48
|
+
# end
|
49
|
+
#
|
50
|
+
# def run
|
51
|
+
# lastPrice = nil
|
52
|
+
# loop do
|
53
|
+
# price = Price.fetch(@symbol)
|
54
|
+
# print "Current price: #{price}\n"
|
55
|
+
# if price != lastPrice
|
56
|
+
# changed # notify observers
|
57
|
+
# lastPrice = price
|
58
|
+
# notify_observers(Time.now, price)
|
59
|
+
# end
|
60
|
+
# sleep 1
|
61
|
+
# end
|
62
|
+
# end
|
63
|
+
# end
|
64
|
+
#
|
65
|
+
# class Price ### A mock class to fetch a stock price (60 - 140).
|
66
|
+
# def Price.fetch(symbol)
|
67
|
+
# 60 + rand(80)
|
68
|
+
# end
|
69
|
+
# end
|
70
|
+
#
|
71
|
+
# class Warner ### An abstract observer of Ticker objects.
|
72
|
+
# def initialize(ticker, limit)
|
73
|
+
# @limit = limit
|
74
|
+
# ticker.add_observer(self)
|
75
|
+
# end
|
76
|
+
# end
|
77
|
+
#
|
78
|
+
# class WarnLow < Warner
|
79
|
+
# def update(time, price) # callback for observer
|
80
|
+
# if price < @limit
|
81
|
+
# print "--- #{time.to_s}: Price below #@limit: #{price}\n"
|
82
|
+
# end
|
83
|
+
# end
|
84
|
+
# end
|
85
|
+
#
|
86
|
+
# class WarnHigh < Warner
|
87
|
+
# def update(time, price) # callback for observer
|
88
|
+
# if price > @limit
|
89
|
+
# print "+++ #{time.to_s}: Price above #@limit: #{price}\n"
|
90
|
+
# end
|
91
|
+
# end
|
92
|
+
# end
|
93
|
+
#
|
94
|
+
# ticker = Ticker.new("MSFT")
|
95
|
+
# WarnLow.new(ticker, 80)
|
96
|
+
# WarnHigh.new(ticker, 120)
|
97
|
+
# ticker.run
|
98
|
+
#
|
99
|
+
# Produces:
|
100
|
+
#
|
101
|
+
# Current price: 83
|
102
|
+
# Current price: 75
|
103
|
+
# --- Sun Jun 09 00:10:25 CDT 2002: Price below 80: 75
|
104
|
+
# Current price: 90
|
105
|
+
# Current price: 134
|
106
|
+
# +++ Sun Jun 09 00:10:25 CDT 2002: Price above 120: 134
|
107
|
+
# Current price: 134
|
108
|
+
# Current price: 112
|
109
|
+
# Current price: 79
|
110
|
+
# --- Sun Jun 09 00:10:25 CDT 2002: Price below 80: 79
|
111
|
+
|
112
|
+
|
113
|
+
#
|
114
|
+
# Implements the Observable design pattern as a mixin so that other objects can
|
115
|
+
# be notified of changes in state. See observer.rb for details and an example.
|
116
|
+
#
|
117
|
+
module Observable
|
118
|
+
|
119
|
+
#
|
120
|
+
# Add +observer+ as an observer on this object. +observer+ will now receive
|
121
|
+
# notifications.
|
122
|
+
#
|
123
|
+
def add_observer(observer)
|
124
|
+
@observer_peers = [] unless defined? @observer_peers
|
125
|
+
unless observer.respond_to? :update
|
126
|
+
raise NoMethodError, "observer needs to respond to `update'"
|
127
|
+
end
|
128
|
+
@observer_peers.push observer
|
129
|
+
end
|
130
|
+
|
131
|
+
#
|
132
|
+
# Delete +observer+ as an observer on this object. It will no longer receive
|
133
|
+
# notifications.
|
134
|
+
#
|
135
|
+
def delete_observer(observer)
|
136
|
+
@observer_peers.delete observer if defined? @observer_peers
|
137
|
+
end
|
138
|
+
|
139
|
+
#
|
140
|
+
# Delete all observers associated with this object.
|
141
|
+
#
|
142
|
+
def delete_observers
|
143
|
+
@observer_peers.clear if defined? @observer_peers
|
144
|
+
end
|
145
|
+
|
146
|
+
#
|
147
|
+
# Return the number of observers associated with this object.
|
148
|
+
#
|
149
|
+
def count_observers
|
150
|
+
if defined? @observer_peers
|
151
|
+
@observer_peers.size
|
152
|
+
else
|
153
|
+
0
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
#
|
158
|
+
# Set the changed state of this object. Notifications will be sent only if
|
159
|
+
# the changed +state+ is +true+.
|
160
|
+
#
|
161
|
+
def changed(state=true)
|
162
|
+
@observer_state = state
|
163
|
+
end
|
164
|
+
|
165
|
+
#
|
166
|
+
# Query the changed state of this object.
|
167
|
+
#
|
168
|
+
def changed?
|
169
|
+
if defined? @observer_state and @observer_state
|
170
|
+
true
|
171
|
+
else
|
172
|
+
false
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
#
|
177
|
+
# If this object's changed state is +true+, invoke the update method in each
|
178
|
+
# currently associated observer in turn, passing it the given arguments. The
|
179
|
+
# changed state is then set to +false+.
|
180
|
+
#
|
181
|
+
def notify_observers(*arg)
|
182
|
+
if defined? @observer_state and @observer_state
|
183
|
+
if defined? @observer_peers
|
184
|
+
for i in @observer_peers.dup
|
185
|
+
i.update(*arg)
|
186
|
+
end
|
187
|
+
end
|
188
|
+
@observer_state = false
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
#blatently stole this code from sugarcube
|
2
|
+
unless defined?(Motion::Project::Config)
|
3
|
+
raise "The rubymotion-observer gem must be required within a RubyMotion project Rakefile."
|
4
|
+
end
|
5
|
+
|
6
|
+
|
7
|
+
Motion::Project::App.setup do |app|
|
8
|
+
# scans app.files until it finds app/ (the default)
|
9
|
+
# if found, it inserts just before those files, otherwise it will insert to
|
10
|
+
# the end of the list
|
11
|
+
insert_point = 0
|
12
|
+
app.files.each_index do |index|
|
13
|
+
file = app.files[index]
|
14
|
+
if file =~ /^(?:\.\/)?app\//
|
15
|
+
# found app/, so stop looking
|
16
|
+
break
|
17
|
+
end
|
18
|
+
insert_point = index + 1
|
19
|
+
end
|
20
|
+
|
21
|
+
Dir.glob(File.join(File.dirname(__FILE__), '/observer/**/*.rb')).reverse.each do |file|
|
22
|
+
app.files.insert(insert_point, file)
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/observer/version.rb', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.name = "rubymotion-observer"
|
6
|
+
gem.version = RubyMotionObserver::Version
|
7
|
+
gem.authors = ["Michael Erasmus"]
|
8
|
+
gem.email = ["michaelerasmus@gmail.com"]
|
9
|
+
gem.description = %q{A RubyMotion compatible version of Ruby's 'observer' lib}
|
10
|
+
gem.summary = %q{A RubyMotion compatible version of Ruby's 'observer' lib}
|
11
|
+
gem.homepage = "https://github.com/michael-erasmus/rubymotion-observer"
|
12
|
+
|
13
|
+
gem.files = `git ls-files`.split($/)
|
14
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
end
|
metadata
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rubymotion-observer
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Michael Erasmus
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-12-12 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: A RubyMotion compatible version of Ruby's 'observer' lib
|
15
|
+
email:
|
16
|
+
- michaelerasmus@gmail.com
|
17
|
+
executables: []
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- .gitignore
|
22
|
+
- Gemfile
|
23
|
+
- LICENSE.txt
|
24
|
+
- README.md
|
25
|
+
- Rakefile
|
26
|
+
- lib/observer/observer.rb
|
27
|
+
- lib/observer/version.rb
|
28
|
+
- lib/rubymotion-observer.rb
|
29
|
+
- rubymotion-observer.gemspec
|
30
|
+
homepage: https://github.com/michael-erasmus/rubymotion-observer
|
31
|
+
licenses: []
|
32
|
+
post_install_message:
|
33
|
+
rdoc_options: []
|
34
|
+
require_paths:
|
35
|
+
- lib
|
36
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
37
|
+
none: false
|
38
|
+
requirements:
|
39
|
+
- - ! '>='
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '0'
|
42
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
43
|
+
none: false
|
44
|
+
requirements:
|
45
|
+
- - ! '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
requirements: []
|
49
|
+
rubyforge_project:
|
50
|
+
rubygems_version: 1.8.24
|
51
|
+
signing_key:
|
52
|
+
specification_version: 3
|
53
|
+
summary: A RubyMotion compatible version of Ruby's 'observer' lib
|
54
|
+
test_files: []
|