Skip to content

Instantly share code, notes, and snippets.

@francescoagati
Created June 19, 2012 13:43
Show Gist options
  • Save francescoagati/2954273 to your computer and use it in GitHub Desktop.
Save francescoagati/2954273 to your computer and use it in GitHub Desktop.
module Observable ported to Opal
#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
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
@francescoagati
Copy link
Author

compared to module implemented in ruby, defined? is substituted by instance_variable_defined?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment