Never been to DZone Snippets before?

Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world

Property change listener (See related posts)

How to implement a Property change listener on ruby class
Origin : http://rawblock.blogspot.com/2007/02/transparent-property-change-listeners.html

   1  
   2  class ListenerSupport
   3   
   4    def self.listen_to(klass, *properties)
   5      setup(klass)
   6      properties.each do |p|
   7        klass.instance_eval do
   8          #rename original method
   9          alias_method "#{p}_orig=", "#{p}="
  10          #create proxy method in it's place that will fire
  11          #changes, and delegate to the original implementation
  12          define_method "#{p}=" do |value|
  13            old_value = send "#{p}"
  14            send "#{p}_orig=",value
  15            fire_property_changed p, old_value, value
  16          end
  17        end
  18      end
  19    end
  20   
  21    def self.setup(klass)
  22      klass.instance_eval do
  23       
  24        define_method :fire_property_changed do |prop, pre, post|
  25          return if pre == post
  26          eval %{
  27            @listeners[prop].each do |l|
  28                l.property_changed(self, prop, pre, post)
  29            end unless @listeners.nil?
  30          }
  31        end unless instance_methods.include? :fire_property_changed
  32       
  33        define_method :add_property_listener do |prop, listener|
  34          eval %{
  35            @listeners = {} if @listeners.nil?
  36            prop_listeners = @listeners.include?(prop) ? @listeners[prop] : []
  37            @listeners[prop] = prop_listeners
  38            prop_listeners << listener unless prop_listeners.include? listener
  39          }
  40        end unless instance_methods.include? :add_property_listener
  41       
  42      end
  43    end
  44   
  45  end


The general idea is that the original class is modified so that all properties that are listened to have their accessor write methods intercepted, and any property change listeners are notified when that property changes.

Let's walk through how it works:

* A standard Ruby class with property accessors is created. e.g.

class RubyBean
attr_accessor :foo, :bar
end

* A call to ListenerSupport.listen_to is made to modify the class to allow properties to be listened to.

ListenerSupport.listen_to RubyBean, :foo, :bar

* listen_to adds methods add_property_listener and fire_property_changed to allow listeners to be added to RubyBean for specific properties.
* listen_to then aliases the original methods foo= and bar= to foo_orig= and bar_orig=. New methods for foo= and bar= are defined that delegate the work to the original method, then call fire_property_changed to notify the listeners.
* Listeners are called, and any custom action (such as GUI component binding) can be carried out.

You need to create an account or log in to post comments to this site.


Click here to browse all 5355 code snippets

Related Posts