Modify instance variable in a method mixed in from external

I have this gem of a parser that does:

def parse_data data
data.chomp!
while data && data.length > 0
data_array = data.split(/\r?\n/,2)
@chunked_data << data_array[0]
data = data_array[1]

  if @chunked_data =~ /(\d{3})(.*)<(.*)>##(.*)##/
      dispatch_data
    @chunked_data = ""
  end
end

end

That is used in several classes as instance methods. Now, I want to
include this method in a module to be DRY. And make this method
available to classes that mixin that module.
The only trouble is, it uses a instance_variable.
Of course…i can keep this method as it is. assuming all the consumer
classes will have their this particular instance variable with same
name.

The other approach could be, as suggested by Eric H. on IRC, is to
have some kind of include, that hookes correct instance variable to
the module upon inclusion in the class.

And this bit…almost escaped me.

If i use set_instance_variable or something like that, then still i
won’t be able to know the name of that particular instance variable
,right?

if i pass the @chunked_data from the any class to the parse_data
method, i would recieve it as a local variable in method and any
changes to the varible will be lost.
Why can’t we have something like C++ reference, where if i modify the
variable in mixed in method, i would effectively change the instance
variable?

Not even that, although in Ruby, AFAIK(which is very little, to tell
the truth) values are passed by reference, even if we pass a local
variable to the parse_data
method and do some modification and try to read back the data in
calling method, changes will be lost.

On 10/18/06, hemant [email protected] wrote:

      dispatch_data

Of course…i can keep this method as it is. assuming all the consumer
classes will have their this particular instance variable with same
name.

Well, if the receiver of parse_data doesn’t have the instance
variable, it will after this method is executed.

In Ruby, instance variables aren’t declared/defined in classes, they
are dynamically added to instances as needed.

I’m not clear on just why you need @chunked_data to persist across
invocations, but the only issue I see with guaranteeing that an
instance of the class has this iv is that it’s not guaranteed to be
initialized, so in the first iteration of your while loop you might be
doing

nil << data_array[0]

which won’t work.

This can be fixed by adding:

@chunked_data ||= “”

before the while loop.

Now one danger is that a class might have an iv called @chunked_data
which it’s using for something else. This seems unlikely but you never
know.

If you do this you need to document the use of @chunked_data.

There are likely better ways to design this if you step back a bit,
but we don’t know enough about the context to help.

The other approach could be, as suggested by Eric H. on IRC, is to
have some kind of include, that hookes correct instance variable to
the module upon inclusion in the class.

I’m not sure what this means, so I can’t comment.

variable in mixed in method, i would effectively change the instance
variable?

Not even that, although in Ruby, AFAIK(which is very little, to tell
the truth) values are passed by reference, even if we pass a local
variable to the parse_data
method and do some modification and try to read back the data in
calling method, changes will be lost.

In Ruby ALL variables are just references, if you mutate the object
referenced by the variable the object will be changed:

irb(main):005:0> def change(arg, value)
irb(main):006:1> arg << value
irb(main):007:1> end
=> nil
irb(main):008:0> a = “hello”
=> “hello”
irb(main):009:0> change(a, " there.")
=> “hello there.”
irb(main):010:0> a
=> “hello there.”
irb(main):011:0>

Any mutating methods invoked against the parameter will change the
underlying object. So rather than

arg = ""

you could use

arg.replace("")

Note that the value of a method is the value of the last expression
executed in the method. So this method returns the value of

arg << value

So you could have parse return the chunked data and ask clients to
pass it back on subsequent calls.

I’m not saying that this is a good design, but you seem to need some
understanding of how variables and objects relate.

Another note on variables and references which trips up folks
accustomed to C-like variables:

irb(main):011:0> b = a
=> “hello there.”
irb(main):012:0> change(a, " Again!")
=> “hello there. Again!”
irb(main):013:0> a
=> “hello there. Again!”
irb(main):014:0> b
=> “hello there. Again!”

Understand that and you should be further along in understanding the
relationship between variables and object in Ruby.


Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

On 10/19/06, Rick DeNatale [email protected] wrote:

relationship between variables and object in Ruby.
Thanks Rick…