I come from a C# background, and have just started programming in Ruby. The thing is, that I need to know how I can raise events in my classes so that various observers can be triggered when things need to happen.
The problem is the books I have on Ruby don't even mention events, let alone provide examples. Is anyone able to help me?
-
I tried writing a GUI library in Ruby with a little C and primarily Ruby. It ended up being so slow I gave up and never released it. But I wrote an event system for it that I tried to make easier than C#'s. I rewrote it a couple times to make it easier to use. I hope it is somewhat helpful.
class EventHandlerArray < Array def add_handler(code=nil, &block) if(code) push(code) else push(block) end end def add raise "error" end def remove_handler(code) delete(code) end def fire(e) reverse_each { |handler| handler.call(e) } end end # with this, you can do: # event.add_handler # event.remove_handler # event.fire (usually never used) # fire_event # when_event # You just need to call the events method and call super to initialize the events: # class MyControl # events :mouse_down, :mouse_up, # :mouse_enter, :mouse_leave # def initialize # super # end # def when_mouse_up(e) # # do something # end # end # control = MyControl.new # control.mouse_down.add_handler { # puts "Mouse down" # } # As you can see, you can redefine when_event in a class to handle the event. # The handlers are called first, and then the when_event method if a handler didn't # set e.handled to true. If you need when_event to be called before the handlers, # override fire_event and call when_event before event.fire. This is what painting # does, for handlers should paint after the control. # class SubControl < MyControl # def when_mouse_down(e) # super # # do something # end # end def events(*symbols) # NOTE: Module#method_added # create a module and 'include' it modName = name+"Events" initStr = Array.new readerStr = Array.new methodsStr = Array.new symbols.each { |sym| name = sym.to_s initStr << %Q{ @#{name} = EventHandlerArray.new } readerStr << ":#{name}" methodsStr << %Q{ def fire_#{name}(e) @#{name}.fire(e) when_#{name}(e) if(!e.handled?) end def when_#{name}(e) end } } eval %Q{ module #{modName} def initialize(*args) begin super(*args) rescue NoMethodError; end #{initStr.join} end #{"attr_reader "+readerStr.join(', ')} #{methodsStr.join} end include #{modName} } end class Event attr_writer :handled def initialize(sender) @sender = @sender @handled = false end def handled?; @handled; end end -
I'm not sure of exactly what you mean but you could probably use exceptions in your classes and raise them on certain "events". If you need event for GUI development then most GUI frameworks define their own event handling style.
Hope this somewhat answers you're question.
Ash : I want to use the Observer Design Pattern. -
The question has already been answered, but there's an observer built right into the standard library if you want to give that a look. I've used it in the past for a small game project, and it works very well.
0 comments:
Post a Comment