Can I make a new function like attr_accessor?

Discussion in 'Ruby' started by Jack, Paul, Dec 15, 2004.

  1. Jack, Paul

    Jack, Paul Guest

    I'm writing a program that has a bunch of components I'd like
    to link together using Java-style property change events.

    So I created a mixin module:

    module Emitter

    def addListener(listener)
    @listeners.push(listener)
    end

    def removeLister(listener)
    @listeners.delete(listener)
    end

    def emit(sym, oldValue)
    @listeners.each { |x| x.propertyChanged(self, sym, oldValue) }
    end

    end

    In my component objects, I just make them include Emitter and invoke
    "emit" on any mutator:

    class ExampleComponent

    include Emitter

    def foo
    @foo
    end

    def foo=(x)
    old = @foo
    @foo = x
    emit:)foo, old)
    end

    end

    I'd like to automate the creation of emitter properties, though. Just
    like I can use attr_accessor to quickly create readable/writeable
    attributes, I'd like a new attr_emitter function to quickly create
    readable/writeable/emitable attributes.

    But I can't figure out how to do that. :( Is it possible? It would
    save me a LOT of redundant typing...

    Thanks all,

    -Paul
     
    Jack, Paul, Dec 15, 2004
    #1
    1. Advertising

  2. On Dec 16, 2004, at 4:08 AM, Jack, Paul wrote:
    > I'd like to automate the creation of emitter properties, though. Just
    > like I can use attr_accessor to quickly create readable/writeable
    > attributes, I'd like a new attr_emitter function to quickly create
    > readable/writeable/emitable attributes.
    >
    > But I can't figure out how to do that. :( Is it possible? It would
    > save me a LOT of redundant typing...


    It's quite possible, and a very useful way to add domain-specific
    syntactic sugar. Basically you define it as a module-level or
    class-level method.

    module Emitter
    def self.attr_emitter( args )
    ...
    end
    end

    Remember that in Ruby there's no distinction between compile-time and
    runtime. So when you define a class like this:

    class ExampleComponent
    include Emitter
    attr_emitter arg1, arg2
    end

    The call to "attr_emitter" isn't actually a special compile-time flag;
    it's a module- or class-level method that you're calling at runtime, as
    you define the class.

    BTW, if you're just coming from Ruby to Java, I wrote an article on my
    blog that you might find really useful: http://fhwang.net/blog/40.html

    Francis Hwang
    http://fhwang.net/
     
    Francis Hwang, Dec 15, 2004
    #2
    1. Advertising

  3. "Thomas Counsell" <> schrieb im Newsbeitrag
    news:...
    > Hi Paul
    >
    > Not tested, but something like this should do the trick:
    >
    > class Class
    > def attr_emitter( *syms )
    > syms.each do |sym|
    > class_eval( "def #{sym}; @#{sym} end" )
    > class_eval( "def #{sym}=(x)
    > old, @#{sym} = @#{sym}, x
    > emit:)#{sym}, old)
    > end" )
    > end
    > end
    > end


    Preferrable put that code into class Module. That way even modules can
    use attr_emitter.

    > Note that I think you also need to define @listeners in your Emitter
    > module ..... (@listeners ||= [] ).push( listener) or some such.


    Yeah. Also you can automate inclusion of the module. So this would be my
    implementation:

    module Emitter
    def listeners; @listeners ||= [] end

    def addListener(listener)
    listeners.push(listener)
    end

    def removeLister(listener)
    listeners.delete(listener)
    end

    def emit(sym, oldValue)
    listeners.each { |x| x.propertyChanged(self, sym, oldValue) }
    end
    end

    class Module
    def attr_emitter(*syms)
    syms.each do |sym|
    class_eval( "def #{sym}; @#{sym} end; def #{sym}=(x) old, @#{sym} =
    @#{sym}, x ; emit:)#{sym}, old) end" )
    end

    include Emitter
    end
    end

    Kind regards

    robert
     
    Robert Klemme, Dec 16, 2004
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Patrick Kowalzick
    Replies:
    5
    Views:
    485
    Patrick Kowalzick
    Mar 14, 2006
  2. active
    Replies:
    4
    Views:
    288
    active
    Apr 3, 2007
  3. Jim Cain
    Replies:
    0
    Views:
    99
    Jim Cain
    Jul 18, 2003
  4. David Garamond
    Replies:
    1
    Views:
    101
    Dan Doel
    Jan 25, 2004
  5. Markus Werner

    attr / attr_accessor

    Markus Werner, Dec 30, 2004, in forum: Ruby
    Replies:
    5
    Views:
    223
    Mark Hubbart
    Dec 31, 2004
Loading...

Share This Page