attr_writer variation

Discussion in 'Ruby' started by Ryan Hinton, Jan 26, 2006.

  1. Ryan Hinton

    Ryan Hinton Guest

    I am working on a nice little document-based app where I would like to
    take selective action based on whether data have been modified (e.g.
    prompt to save before exit). When I imagine writing a bunch of
    "memberVariable=(newVar)" methods, all with the same pattern for the
    guts, I think there must be a better way.

    How does attr_writer do this? I tried to figure out how to do
    something similar in vanilla Ruby, but I don't see a way to
    programmatically define a new method. Would I have to write a C
    extension for this?

    Here is roughly what I want.

    module AttrWriterTrackModified
    def attr_writer(*syms)
    syms.each do |sym|
    eval("def #{sym}=(val)
    if @#{sym} != val
    @#{sym} = val
    @modified = true
    end
    end;")
    end
    end
    end
    Ryan Hinton, Jan 26, 2006
    #1
    1. Advertising

  2. Ryan Hinton

    Ross Bamford Guest

    On Thu, 26 Jan 2006 22:15:50 -0000, Ryan Hinton <> wrote:

    > Here is roughly what I want.
    >
    > module AttrWriterTrackModified
    > def attr_writer(*syms)
    > syms.each do |sym|
    > eval("def #{sym}=(val)
    > if @#{sym} != val
    > @#{sym} = val
    > @modified = true
    > end
    > end;")
    > end
    > end
    > end
    >


    Maybe I'm missing something, but you're almost there. You could try this:

    class Module
    def attr_writer(*syms)
    syms.each do |sym|
    module_eval <<-EOC
    def #{sym}=(val)
    if @#{sym} != val
    @#{sym} = val
    @modified = true
    end
    end
    EOC
    end
    end
    end

    Just use it as normal:

    class TryIt
    attr_reader :eek:ne, :two, :three, :modified
    attr_writer :eek:ne, :two, :three
    def initialize(one, two, three)
    @one, @two, @three = one, two, three
    @modified = false
    end
    end

    p t = TryIt.new(1,2,3)
    p t.one
    p t.two
    p t.three
    p t.modified

    p t.two = 4
    p t.one
    p t.two
    p t.three
    p t.modified

    Output:

    #<TryIt:0xb7facae4 @modified=false, @three=3, @two=2, @one=1>
    1
    2
    3
    false
    1
    4
    3
    true

    (Hmm, I bet you could make an attr_initializer or something to cover that
    initialize method too ... ;))

    Hope that helps.

    --
    Ross Bamford -
    Ross Bamford, Jan 26, 2006
    #2
    1. Advertising

  3. By the way, here's a simple newbie question: what is the difference
    between defining some method with class_eval in Class class and with
    module_eval in Module class?
    Vladimir Agafonkin, Jan 27, 2006
    #3
  4. Ryan Hinton

    Ross Bamford Guest

    On Fri, 27 Jan 2006 00:12:56 -0000, Vladimir Agafonkin
    <> wrote:

    > By the way, here's a simple newbie question: what is the difference
    > between defining some method with class_eval in Class class and with
    > module_eval in Module class?
    >


    Aside from the usual difference between class instance and module instance
    methods, I don't think there is a difference. Module.class_eval is an
    alias for Module.module_eval.

    --
    Ross Bamford -
    Ross Bamford, Jan 27, 2006
    #4
  5. Ryan Hinton

    Ryan Hinton Guest

    That works! But I don't want the tracking all the time. Can I put it
    in a module to mix-in? I've been fiddling trying different variations,
    but apparently I am missing the reason why your example works.
    Ryan Hinton, Jan 27, 2006
    #5
  6. Ryan Hinton

    Ryan Hinton Guest

    I think I figured it out, but I'm still a little hazy so any
    clarification is great. "include" merges the definition of the module
    and the class, so instances of the class effectively have two
    superclasses. "extend" adds the instance methods from a module to the
    current object. When I call attr_writer, I am effectively calling a
    method in the context of the current class being defined (self ==
    MyClass). Its methods are defined in Class and/or Method, so I can
    redefine attr_writer there. If I don't want to do that, I can "extend"
    a class being defined with a module I write that defines and
    attr_writer method. Then using attr_writer will do what I want.
    However, I will need to do this in each class I want this behavior.

    I am still confused by module_function. Normally the instance methods
    of a module are passed on in an "include", but module_function makes a
    method a module method (Mod.meth) _and_ passes it on as a private
    instance method in an "include". This seems really quirky.
    Ryan Hinton, Jan 27, 2006
    #6
    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. Robert William Vesterman

    Forcing attr_writer to a type?

    Robert William Vesterman, Aug 27, 2005, in forum: Ruby
    Replies:
    4
    Views:
    151
    Malte Milatz
    Aug 28, 2005
  2. Joe

    Using attr_writer?

    Joe, Feb 26, 2006, in forum: Ruby
    Replies:
    5
    Views:
    110
  3. Joe Ruby MUDCRAP-CE

    attr_reader + attr_writer?

    Joe Ruby MUDCRAP-CE, Oct 13, 2006, in forum: Ruby
    Replies:
    6
    Views:
    105
    Trans
    Oct 13, 2006
  4. Markus Hohenhaus
    Replies:
    3
    Views:
    143
    Phrogz
    May 9, 2007
  5. aidy

    attr_writer and hash

    aidy, Jul 14, 2007, in forum: Ruby
    Replies:
    2
    Views:
    87
    Sharon Phillips
    Jul 14, 2007
Loading...

Share This Page