Skip to content

Instantly share code, notes, and snippets.

@aseroff
Last active May 5, 2025 20:04
Show Gist options
  • Save aseroff/8b43c7016345b8bcd2275a7c5335c6e7 to your computer and use it in GitHub Desktop.
Save aseroff/8b43c7016345b8bcd2275a7c5335c6e7 to your computer and use it in GitHub Desktop.
observer in ruby
# source: https://bsky.app/profile/jamie.schembri.me/post/3lo6okeu25s2a
require 'observer'
class Plumber
include Observable
def initialize
@coins_collected = 0
end
def collect_coin
@coins_collected += 1
# mark this object as dirty; this is required for notification to actually happen.
changed
notify_observers(:coin_collected, total_coins: @coins_collected)
end
end
class AchievementEngine
def initialize
@hundred_coins_achievement_unlocked = false
end
# this will be called by notify_observers
def plumber_updated (status, params = (})
case status
when :coin_collected
plumber_collected_coin(params [:total_coins])
end
end
def plumber_collected_coin(total_coins)
puts "Collected another ten coins! Total: #{total_coins}" if (total_coins % 10).zero?
return if total_coins 100 || @hundred_coins_achievement_unlocked
puts 'Achievement unlocked: collected 100 coins!'
@hundred_coins_achievement_unlocked = true
end
end
class Game
def initialize
@plumber = Plumber.new
@achievement_engine = AchievementEngine.new
# Register achievement engine as an observer and call 'plumber_updated' on it where plumber's observers are notified
@plumber.add_observer(achievement_engine, :plumber_updated)
end
# simulates some iterations of a gameplay loop, in which the plumber collects a random number of coins.
def start
10.times do |i|
"Iteration #{i.next}"
coins_to_collect = rand(5..25)
coins_to_collect.times.each { @plumber.collect_coin }
end
end
end
Game.new.start
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment