Eugen
Eugen

Reputation: 155

Make some kind of Event System in ruby

I have this kind of code:

module EventSystem
  @@events = {
    :on_minute_change = [],
    :on_hour_change = []
  }

  def self.register_action(event, action)
    @@events[event].push(action)
  end

  def self.notify_event(event)
    @@events[event].each do |action|
      Actions.send(action)
    end
  end
end

module Actions
  def self.make_something
    p "something is happening"
  end

  def self.make_something_else
    p "something else is happening"
  end
end

EventSystem.register_action(:on_minute_change, :make_something)
EventSystem.register_action(:on_minute_change, :make_something_else)
EventSystem.register_action(:on_hour_change, :make_something)

class Own_Time
  def next_minute
    # minute += 1
    EventSystem.notify_event(:on_minute_change)
  end

  def next_hour
    # hour += 1
    EventSystem.notify_event(:on_hour_change)
  end
end

@own_time = Own_Time.new

@own_time.next_minute
@own_time.next_minute
@own_time.next_hour

OUTPUT:

"something is happening"
"something else is happening"

"something is happening"
"something else is happening"

"something is happening"

The reason for all of this is, that I want to have a base code and add new optional addons to the base to keep it modular and changeable. I could also for example alias the next_minute method instead of having an event which will call all registered methods. But because I will have many addons this would mean that I will have to use many aliases so I thought of a simpler way.

Now Im wondering if my approach is ok or if there are some flaws and problems with my code. Any help is appreciated.

Upvotes: 0

Views: 244

Answers (1)

Dave N
Dave N

Reputation: 398

It seems to me you're trying to recreate an already very well understood design pattern, the Observer Pattern. The Ruby Standard Library already has a module that will help you accomplish this. It is documented here. I've given you an example below, but the example in the documentation is more thorough. Disclaimer: it's getting late, so I apologize if I've completely misunderstood your question.

class Timer
  include Observable

  def run
    # TODO: add code to check time here
    # TODO: check whether minute or hours have changed here

    # call this when minute is changed
    change 

    # notify the objects observing the timer and call
    # the method that you want to trigger
    # NOTE: you can pass in args here that might need
    # to be passed into the method on the receiving
    # observer
    notify_observers(args)
  end
end

class ExampleMaker
  def make_something(args)
    # do something with args
  end
end

timer = Timer.new
maker = ExampleMaker.new
timer.add_observer(maker, :make_something)

Upvotes: 1

Related Questions