Created
June 19, 2012 13:43
-
-
Save francescoagati/2954273 to your computer and use it in GitHub Desktop.
module Observable ported to Opal
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#hacking Kernel module for add loop_every | |
module Kernel | |
def loop_every(n,&blk) | |
blk.call | |
n=n*1000 | |
`setInterval(function() {` | |
blk.call | |
`},n);` | |
end | |
end | |
class Ticker ### Periodically fetch a stock price. | |
include Observable | |
def initialize(symbol) | |
@symbol = symbol | |
end | |
def run | |
lastPrice = nil | |
loop_every 10 do | |
price = Price.fetch(@symbol) | |
puts "Current price: #{price}\n" | |
if price != lastPrice | |
changed # notify observers | |
lastPrice = price | |
notify_observers(Time.now, price) | |
end | |
#sleep 10 | |
end | |
end | |
end | |
class Price ### A mock class to fetch a stock price (60 - 140). | |
def Price.fetch(symbol) | |
60 + rand(80) | |
end | |
end | |
class Warner ### An abstract observer of Ticker objects. | |
def initialize(ticker, limit) | |
@limit = limit | |
ticker.add_observer(self) | |
end | |
end | |
class WarnLow < Warner | |
def update(time, price) # callback for observer | |
if price < @limit | |
puts "--- #{time.to_s}: Price below #@limit: #{price}\n" | |
end | |
end | |
end | |
class WarnHigh < Warner | |
def update(time, price) # callback for observer | |
if price > @limit | |
puts "+++ #{time.to_s}: Price above #@limit: #{price}\n" | |
end | |
end | |
end | |
ticker = Ticker.new("MSFT") | |
WarnLow.new(ticker, 80) | |
WarnHigh.new(ticker, 120) | |
ticker.run |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Observable | |
def add_observer(observer, func=:update) | |
@observer_peers = {} unless instance_variable_defined?("observer_peers") | |
unless observer.respond_to? func | |
raise NoMethodError, "observer does not respond to `#{func.to_s}'" | |
end | |
puts @observer_peers.class | |
@observer_peers[observer] = func | |
end | |
# | |
# Delete +observer+ as an observer on this object. It will no longer receive | |
# notifications. | |
# | |
def delete_observer(observer) | |
@observer_peers.delete observer if instance_variable_defined?("observer_peers") | |
end | |
# | |
# Delete all observers associated with this object. | |
# | |
def delete_observers | |
@observer_peers.clear if instance_variable_defined?("observer_peers") | |
end | |
# | |
# Return the number of observers associated with this object. | |
# | |
def count_observers | |
if instance_variable_defined?("observer_peers") | |
@observer_peers.size | |
else | |
0 | |
end | |
end | |
# | |
# Set the changed state of this object. Notifications will be sent only if | |
# the changed +state+ is +true+. | |
# | |
def changed(state=true) | |
@observer_state = state | |
end | |
# | |
# Query the changed state of this object. | |
# | |
def changed? | |
if is_defined? @observer_state and @observer_state | |
true | |
else | |
false | |
end | |
end | |
# | |
# If this object's changed state is +true+, invoke the update method in each | |
# currently associated observer in turn, passing it the given arguments. The | |
# changed state is then set to +false+. | |
# | |
def notify_observers(*arg) | |
if instance_variable_defined?("observer_state") | |
if instance_variable_defined?("observer_peers") | |
@observer_peers.each { |k, v| | |
k.send v, *arg | |
} | |
end | |
@observer_state = false | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
compared to module implemented in ruby, defined? is substituted by instance_variable_defined?