Forum: Ruby Simple Question About Deleting Instances

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Nathan O. (Guest)
on 2006-04-07 19:58
I have a case where I'd like to delete an instance of a class I made
myself. How do I do that?

The problem I'm having is that while iterating through a loop, I'm
constantly trying to reassign the same variable name to a different
instance, but Ruby is just adding the new data to the old, so I'm
mounting piles and piles of unwanted data on an instance.

I googled, but couldn't find a solution. Odd!
zdennis (Guest)
on 2006-04-07 20:02
(Received via mailing list)
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Nathan O. wrote:
> I have a case where I'd like to delete an instance of a class I made
> myself. How do I do that?
>
> The problem I'm having is that while iterating through a loop, I'm
> constantly trying to reassign the same variable name to a different
> instance, but Ruby is just adding the new data to the old, so I'm
> mounting piles and piles of unwanted data on an instance.

Some code would help. Saying:

a = 1
a = 2
a = 3

Will *always* reassign variable 'a' to something new. My guess is you
aren't really reassigning your reference to a new value. But
it's hard to say without any code cause no one can tell what you are
doing.

Zach
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org

iD8DBQFENo3JMyx0fW1d8G0RAqN4AJ4yQ+netLhX3nqNAKM4k8fj/kYSAQCfT899
zFfsDvypayWzWW4sLBdJQS4=
=DELC
-----END PGP SIGNATURE-----
Nathan O. (Guest)
on 2006-04-07 20:12
> Some code would help. Saying: ...

require 'my_stuff' # Includes the Report class

file_list = Dir.new("reports")
yes_list = []
no_list = []
file_list.each do |file|
   if file_name =~ /yes/
      report = Report.new(file_name)
      yes_list.push(report.ID_list)
   elsif file_name =~ /no/
      report = Report.new(file_name)
      no_list.push(report.ID_list)
   end
end

puts yes_list.inspect
puts no_list.inspect



Both yes and no lists gather way more data than they're supposed to and
based on the excess data I'm seeing, it looks like it just isn't
deleting old data from the old instance of report.

I've (feebly) tried report.delete, report.replace, and report = nil at
the end of each if block, if that helps convey my goal.
Mark Van H. (Guest)
on 2006-04-07 20:23
(Received via mailing list)
I think you problems is in the report class. Each time you do report =
Report.new, you won't be getting any data carried over from the last
report
object. Is report.ID_list a method on the class? or on the instance? The
only way I can see it keeping data around is if you have some type of
data
structure as a class variable, when you meant it to be an instance
variable.

mark
Nathan O. (Guest)
on 2006-04-07 20:31
Mark Van H. wrote:
> I think you problems is in the report class. Each time you do report =
> Report.new, you won't be getting any data carried over from the last
> report
> object. Is report.ID_list a method on the class? or on the instance? The
> only way I can see it keeping data around is if you have some type of
> data
> structure as a class variable, when you meant it to be an instance
> variable.
>
> mark

Ah, this is a question I've had for a while. Last time I looked in to
it, I didn't find a real answer, but my code started working, so I ran
with it.

How do I define the difference between class variables and instance
variables? Class methods and instance methods?

Currently, all my methods for my classes are defined as:

def method_name()
...
end

And my variables are all defined as:

@@var = ...

I couldn't figure out any other way to make variables available to
methods of the class they belonged to, but doing it this way worked
<shrug>.
zdennis (Guest)
on 2006-04-07 20:42
(Received via mailing list)
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Nathan O. wrote:
>>
> Currently, all my methods for my classes are defined as:
>
> def method_name()
> ...
> end

This is an instance method. It works on the instance of Report.

>
> And my variables are all defined as:
>
> @@var = ...

This is a class variable. All Reports will share this variable. You
probably want to make it an instance variable with one @ symbols.

@var = ...

>
> I couldn't figure out any other way to make variables available to
> methods of the class they belonged to, but doing it this way worked
> <shrug>.

For more information you may want to check out the Learn To Program book
by Chris P.s. http://pine.fm/LearnToProgram/

Specfically http://pine.fm/LearnToProgram/?Chapter=09  nd scroll down to
Instance Variables.

Zach





-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org

iD8DBQFENpa7Myx0fW1d8G0RAtW+AJ9OK1RnQnuud/rbdbsUl7FU4fdroQCfeO9k
O6F5VO92CGpw/QSuX1sFB7U=
=wii5
-----END PGP SIGNATURE-----
Nathan O. (Guest)
on 2006-04-07 20:47
zdennis wrote:
>> def method_name()
>> ...
>> end
>
> This is an instance method. It works on the instance of Report.
>
>>
>> And my variables are all defined as:
>>
>> @@var = ...
>
> This is a class variable. All Reports will share this variable. You
> probably want to make it an instance variable with one @ symbols.
>
> @var = ...

I replaced all instances of "@@" with "@" in my script since I don't
need any class variables. Now, Ruby generates errors telling me that all
of these variables are unknown when referenced from instance methods.

Do I need to make any special kinds of accessors or anything?

And on that note, how do I do something like attr_reader :@@var? Ruby
doesn't seem to know what to do when I put those @s there.
zdennis (Guest)
on 2006-04-07 20:57
(Received via mailing list)
Nathan O. wrote:
>> probably want to make it an instance variable with one @ symbols.
>>
>> @var = ...
>
> I replaced all instances of "@@" with "@" in my script since I don't
> need any class variables. Now, Ruby generates errors telling me that all
> of these variables are unknown when referenced from instance methods.

Can you post code along with your questions ? It makes it so much easier
to help.

>
> Do I need to make any special kinds of accessors or anything?
>
> And on that note, how do I do something like attr_reader :@@var? Ruby
> doesn't seem to know what to do when I put those @s there.

When using attr_reader, attr_writer, attr_accessor you dont need to
include the @ symbols.

class A
  attr_accessor :var # this will create an instance variable @var
                     # plus the get/set methods for var on an instance
                     # of A

  class << self
     attr_accessor :foo # this will create a class method var for you
                        # plus the get/set methods for var on the class
                        # A. The var will be created as an instance
                        #variable @var on the class A
  end
end

a  = A.new
a.var = 5
puts a.var #outputs 5

b = A.new
b.var = 10
puts  b.var #outputs 10

A.foo = 100
puts A.foo  #outputs 100

Please do read the Chris P.s Learn To Program from my last post. It
seems you are guessing at what goes where and you need little a
guidance, Chris P.s Learn to Program will help you get started in the
right direction.

Zach
Nathan O. (Guest)
on 2006-04-07 21:08
zdennis wrote:
> Can you post code along with your questions ? It makes it so much easier
> to help.

class A
   @@a = 1
   @b = 2
   def say_stuff()
      puts @@a # Works
      puts @b  # Doesn't work
   end
end

> When using attr_reader, attr_writer, attr_accessor you dont need to
> include the @ symbols.
>
> class A
>   attr_accessor :var # this will create an instance variable @var
>                      # plus the get/set methods for var on an instance
>                      # of A
>
>   class << self
>      attr_accessor :foo # this will create a class method var for you
>                         # plus the get/set methods for var on the class
>                         # A. The var will be created as an instance
>                         #variable @var on the class A
>   end
> end
>
> a  = A.new
> a.var = 5
> puts a.var #outputs 5
>
> b = A.new
> b.var = 10
> puts  b.var #outputs 10
>
> A.foo = 100
> puts A.foo  #outputs 100

That seems way more convoluted than just:

class A
   @@var = ""
   attr_accessor :@@var
end

Class << self creates class variables by the same name as instance
variables? So you'd have both @@var and @var? Is there a specific reason
for this? It seems HIGHLY unpredictable.

> Please do read the Chris P.s Learn To Program from my last post. It
> seems you are guessing at what goes where and you need little a
> guidance, Chris P.s Learn to Program will help you get started in the
> right direction.

I'll at least give it a glance at lunch time. Sounds promising. Thanks!
zdennis (Guest)
on 2006-04-07 21:21
(Received via mailing list)
Nathan O. wrote:
>    end
> end

You are creating an instance variable @b on your class A. The class A is
an instance of the class Class, so it to can have instance variables.

You want to define your instance variable @b inside of your initialize
method, or you want to use attr_* methods to do this for you:

  class A
    @@a = 1

    def initialize
      @b = 2
    end

    def say_stuff
       puts @@a
       puts @b
    end
  end

  a = A.new
  a.say_stuff

Or:

  class A
    attr_accessor :b

    @@a = 1

    def initialize
      @b = 2
    end

    def say_stuff
       puts @@a
       puts @b
    end
  end

  a = A.new
  a.b = 10
  a.say_stuff

You should really check this stuff out in IRB as well. Open a shell or
cmd.exe and type 'irb'.

Zach
Nathan O. (Guest)
on 2006-04-07 21:32
zdennis wrote:
> You are creating an instance variable @b on your class A. The class A is
> an instance of the class Class, so it to can have instance variables.

Not to be a whiner, but is there a reason we can't just do attr_accessor
:@@var? What you're saying is logical, but it seems like we're getting
from point A to point B via point F.

>   class A
>     @@a = 1
>
>     def initialize
>       @b = 2
>     end
>
>     def say_stuff
>        puts @@a
>        puts @b
>     end
>   end
>
>   a = A.new
>   a.say_stuff
>
> Or:
>
...
>
> You should really check this stuff out in IRB as well. Open a shell or
> cmd.exe and type 'irb'.

I do use irb (well, I write little test scripts and then run them
through regular ruby, but same thing). I've done something else wrong:
when I try this specifically the way you've outlined in a small test
script, it works. Doing it that way in the script I'm working on
generates errors. I guess I've got something else to look in to.
Nathan O. (Guest)
on 2006-04-07 21:38
Nathan O. wrote:
> I do use irb (well, I write little test scripts and then run them
> through regular ruby, but same thing). I've done something else wrong:
> when I try this specifically the way you've outlined in a small test
> script, it works. Doing it that way in the script I'm working on
> generates errors. I guess I've got something else to look in to.

Hmmm!!! My code actually *is* working! The problem: it's a CGI script.
On the command line, it runs fine. From a browser, it breaks down!

... this is going to take a while to debug. Does anyone have any idea
why using only class variables would work but instance variables
wouldn't? I suspect tainting, but how is any of this tainted?
Nathan O. (Guest)
on 2006-04-07 21:43
Nathan O. wrote:
> ... this is going to take a while to debug. Does anyone have any idea
> why using only class variables would work but instance variables
> wouldn't? I suspect tainting, but how is any of this tainted?

Now I just feel like I'm spamming the forum with my newbieness...

For some reason, having methods for accessors (def fileName;return
@fileName;end) works on the command line but not through a browser.
Using attr_accessor instead, it works.

That part of my code was a vestige from previous habits, so I wont miss
it, but does anyone have any idea why it wouldn't have worked to write
accessor methods?
zdennis (Guest)
on 2006-04-07 21:46
(Received via mailing list)
Nathan O. wrote:
> zdennis wrote:
>> You are creating an instance variable @b on your class A. The class A is
>> an instance of the class Class, so it to can have instance variables.
>
> Not to be a whiner, but is there a reason we can't just do attr_accessor
> :@@var? What you're saying is logical, but it seems like we're getting
> from point A to point B via point F.

No. You just need to understand how classes and instances of a class
work.

attr_* methods set instance variables and get/set methods on an instance
of a class. It does this using symbols.

  class A
    attr_accessor :b
  end

:b will point to instance variable @b, on an instance of A.

If you want to use attr_* to set class variables you need to work on the
instance of the class itself. That is why we do:

  class A
    class << self
      attr_accessor :class_var
    end
  end

Because "class << self" opens up the instance of class A. And :class_var
will map to a '@class_var' instance variable on your class itself (and
not on an instance of your class).

If you want further shortcuts check out the facets or traits libraries
on rubyforge. They may have what you are looking for, although I would
ask you to understand how ruby works first before trying to shortcut
this.

Zach
zdennis (Guest)
on 2006-04-07 21:49
(Received via mailing list)
Nathan O. wrote:
> Nathan O. wrote:
>> ... this is going to take a while to debug. Does anyone have any idea
>> why using only class variables would work but instance variables
>> wouldn't? I suspect tainting, but how is any of this tainted?
>
> Now I just feel like I'm spamming the forum with my newbieness...
>
> For some reason, having methods for accessors (def fileName;return
> @fileName;end) works on the command line but not through a browser.
> Using attr_accessor instead, it works.

The ruby-esque way to write methods is lowercase with underscores
separating words:

  def file_name; end

Scratch the lowerCamelCase and save the UpperCamelCase for class and
module definitions.

Zach
zdennis (Guest)
on 2006-04-07 21:52
(Received via mailing list)
zdennis wrote:
> attr_* methods set instance variables and get/set methods on an instance
>
>   class A
>     class << self
>       attr_accessor :class_var
>     end
>   end
>
> Because "class << self" opens up the instance of class A. And :class_var
> will map to a '@class_var' instance variable on your class itself (and
> not on an instance of your class).

class A
end

# this creates an instance of your class, which is of class A
a = A.new

# this opens the instance of class A itself, which is of class Class
class A
  class << self
  end
end

Zach
Nathan O. (Guest)
on 2006-04-07 21:53
zdennis wrote:
> Nathan O. wrote:
> No. You just need to understand how classes and instances of a class
> work.

I understand how it works. In Ruby, (almost) everything is an object.
Therefor, when I'm defining a class and I want a class variable to be
accessible, I need to say so in defining the class, not in defining how
instances of the class work.

Again, I understand how it works. I'm just trying to point out that
sure, doing it this way proves that the coder knows how Ruby works, but
it also makes the code reader think more than maybe they should need to.
This works in direct contrast with the perception that Ruby lets you
focus more on solving problems and less on writing code.

Just my perception as someone who just spent half a day trying to work
around language particularities.
zdennis (Guest)
on 2006-04-07 22:04
(Received via mailing list)
Nathan O. wrote:
> Again, I understand how it works. I'm just trying to point out that
> sure, doing it this way proves that the coder knows how Ruby works, but
> it also makes the code reader think more than maybe they should need to.
> This works in direct contrast with the perception that Ruby lets you
> focus more on solving problems and less on writing code.
>
> Just my perception as someone who just spent half a day trying to work
> around language particularities.
>

If you want you can extend ruby to do what *you* want. Ruby gives you
this flexibility...

class Class
   def attr_class_accessor arg
     instance_eval "class << self ; attr_accessor :#{arg} ; end"
   end
end

class A
  attr_class_accessor :b
end



Zach
Nathan O. (Guest)
on 2006-04-07 22:12
zdennis wrote:
> If you want you can extend ruby to do what *you* want. Ruby gives you
> this flexibility...
>
> class Class
>    def attr_class_accessor arg
>      instance_eval "class << self ; attr_accessor :#{arg} ; end"
>    end
> end
>
> class A
>   attr_class_accessor :b
> end

Yes, but... that still means that someone has to think about more
implementation details than should (in my opinion) be necessary :-) You
know what I mean?
zdennis (Guest)
on 2006-04-07 22:32
(Received via mailing list)
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Nathan O. wrote:
>>
>>class A
>>  attr_class_accessor :b
>>end
>
>
> Yes, but... that still means that someone has to think about more
> implementation details than should (in my opinion) be necessary :-) You
> know what I mean?
>

I had to think about half a second, and then type for about 8 seconds.
Just copy and paste the code and put it in a file that you
require on your projects, and you won't have to think. I will think for
you. Matz is busy solving bigger problems and conquering
better obstacles. So he doesn't have to think about this, I will put my
brain to work for him.

  class Class
    def attr_class_accessor arg
      instance_eval "class << self ; attr_accessor :#{arg} ; end"
    end

    def attr_class_reader arg
      instance_eval "class << self ; attr_reader :#{arg} ; end"
    end

    def attr_class_writer arg
      instance_eval "class << self ; attr_writer :#{arg} ; end"
    end
  end

If you feel this stronlgy about your desire to simplify this, perhaps
you should submit it as an RCR, http://www.rcrchive.net. I
am not saying I think your idea to simplify this into a builtin part of
ruby is a bad thing, but I think that you should not
abolish your ability to think. Ruby gives you power, use it. And if you
think it can be made better, submit a patch or submit an RCR.

Matz gives you the power to influence the langauge, I challenge you to
do so.

Zach
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org

iD8DBQFENrBSMyx0fW1d8G0RAgMYAJ9vFyS/H5Jn/jYdxIZgr57y+i6N5gCfThBe
zpwrWvyW5OX6BC2oJxVAo1Q=
=4Jlf
-----END PGP SIGNATURE-----
Nathan O. (Guest)
on 2006-04-08 00:13
zdennis wrote:
> I had to think about half a second, and then type for about 8 seconds.
> Just copy and paste the code and put it in a file that you
> require on your projects, and you won't have to think. I will think for
> you. Matz is busy solving bigger problems and conquering
> better obstacles. So he doesn't have to think about this, I will put my
> brain to work for him.
>
>   class Class
>     def attr_class_accessor arg
>       instance_eval "class << self ; attr_accessor :#{arg} ; end"
>     end
>
>     def attr_class_reader arg
>       instance_eval "class << self ; attr_reader :#{arg} ; end"
>     end
>
>     def attr_class_writer arg
>       instance_eval "class << self ; attr_writer :#{arg} ; end"
>     end
>   end
>
> If you feel this stronlgy about your desire to simplify this, perhaps
> you should submit it as an RCR, http://www.rcrchive.net. I
> am not saying I think your idea to simplify this into a builtin part of
> ruby is a bad thing, but I think that you should not
> abolish your ability to think. Ruby gives you power, use it. And if you
> think it can be made better, submit a patch or submit an RCR.
>
> Matz gives you the power to influence the langauge, I challenge you to
> do so.

It's not so much that I feel strongly as much as that it perplexes me. I
guess I just wanted to make sure my meds haven't been replaced with
crazy pills.

I thought of this, too: isn't it odd that you can define class variables
in a definition of how instances of a class should work, but you can't
define their accessors? It seems inconsistent. If it's agreed that this
is inconsistent, I'll post something to the site you mentioned, but if
it's that way for a reason, I'll just take your much appreciated advice,
learn that much more, and be that much less of a newbie.
Austin Z. (Guest)
on 2006-04-08 01:53
(Received via mailing list)
On 4/7/06, Nathan O. <removed_email_address@domain.invalid> wrote:
> zdennis wrote:
[...]
> newbie.
I'm not sure you're clear on the concept (I don't mean that meanly).

Consider:

  class Foo
    @bar = 5    # the instance variable @bar of <Foo:class> (1)
    @@bar = 5   # the class variable @bar of <Foo:class> (2)

    def initialize
      @bar = 5  # the instance variable @bar of a Foo instance. (3)
    end
  end

When you do:

  class Foo
    class << self
      attr_accessor    :bar
    end
  end

You are accessing (1). (2) is not affected.

I addressed some of the reasons *why* you wouldn't simply do:

  attr_accessor :@var

in my article on Symbols in January (on the O'Reilly Ruby blog), but
remember that attr_accessor defines methods. There's no difference
between the types of code here. In fact, if you run "ruby -w" on this
code, you'll get warnings about method redefinitions for the latter two.

  class Foo
    attr_accessor :bar

    def bar; @bar; end
    def bar=(x); @bar = x; end
  end

Jumping back to the Pickaxe:

  class Song
    attr_accessor :duration # in seconds

    def minutes=(x); @duration = (x * 60).to_i; end
    def minutes; @duration / 60; end
  end

  s = Song.new
  s.duration = 60
  s.minutes # => 1
  s.minutes = 2.3
  s.duration # => 138

For documentation purposes, I'll sometimes do the following:

  class Song
    # The duration of the song in seconds.
    attr_accessor :seconds
    # The duration of the song in minutes.
    attr_accessor :minutes
    remove_method :minutes, :minutes=
    def minutes=(m) # :nodoc:
      @seconds = (x * 60).to_i
    end
    def minutes # :nodoc:
      @duration / 60
    end
  end

So using attr_accessor doesn't declare a variable; it declares a pair of
methods that access and may instantiate a variable, but doesn't have to.
And *that* is why doing "attr_accessor :@var" really wouldn't be
appropriate.

-austin
Nathan O. (Guest)
on 2006-04-08 02:10
Austin Z. wrote:
> So using attr_accessor doesn't declare a variable; it declares a pair of
> methods that access and may instantiate a variable, but doesn't have to.
> And *that* is why doing "attr_accessor :@var" really wouldn't be
> appropriate.

I guess to put my question simply, why is there a single context in
which I can define class variables but not class methods (accessors for
these variables)? Shouldn't the two be handled in the same context /
scope / block / area-of-code?
Austin Z. (Guest)
on 2006-04-08 05:13
(Received via mailing list)
On 4/7/06, Nathan O. <removed_email_address@domain.invalid> wrote:
> Austin Z. wrote:
>> So using attr_accessor doesn't declare a variable; it declares a pair
>> of methods that access and may instantiate a variable, but doesn't
>> have to. And *that* is why doing "attr_accessor :@var" really
>> wouldn't be appropriate.
> I guess to put my question simply, why is there a single context in
> which I can define class variables but not class methods (accessors
> for these variables)? Shouldn't the two be handled in the same context
> / scope / block / area-of-code?

No. To clarify my statement:

  #attr_accessor creates a pair of instance methods that access and
  may instantiate an instance variable, but don't have to.

Instance variables are always bound to a particular value of self. (I'm
not *quite* sure where class variables reside.)

  >> class Foo
  >>   p "#{self.inspect} (#{self.object_id})"
  >>   class << self
  >>     p "#{self.inspect} (#{self.object_id})"
  >>     def myself
  >>       p "#{self.inspect} (#{self.object_id})"
  >>     end
  >>   end
  >>   myself
  >>   def myself
  >>     p "#{self.inspect} (#{self.object_id})"
  >>   end
  >> end
  "Foo (23584680)"
  "#<Class:Foo> (23584668)"
  "Foo (23584680)"
  => nil
  >> Foo.new.myself
  "#<Foo:0x2cfa7c8> (23581668)"
  => nil
  >>

So, within the scope of "class Foo", self is a particular object (known
as Foo, oddly enough ;). Within the "class << self" inside of "class
Foo", self is a wholy different object. Within the instance method
declared in "class << self", self is once again the Foo object.

Calling "myself" from the scope of "class Foo" demonstrates this. I
could call Foo.myself can get the same result. What that shows is that
if I use @var inside of the scope of "class Foo", I'm *actually* using
an instance variable inside of that object (of type Class).

Where you seem to be having problem is that unlike other languages,
a simple declaration in Ruby isn't. Declaration is *execution*. There is
no "compile" stage followed by a "run" stage. The two happen together
(as demonstrated above).

"class Foo", "class << self", and "def myself" all change scope and the
meaning of "self" in that scope.

Does that help?

-austin
Nathan O. (Guest)
on 2006-04-08 08:45
Austin Z. wrote:
> No. To clarify my statement:
>
>   #attr_accessor creates a pair of instance methods that access and
>   may instantiate an instance variable, but don't have to.
>
> Instance variables are always bound to a particular value of self. (I'm
> not *quite* sure where class variables reside.)
>
...
>
> "class Foo", "class << self", and "def myself" all change scope and the
> meaning of "self" in that scope.
Way, way over my head, but that probably has something to do with the
two-year-old demanding that I stop reading and start wrestling with him.
I'll sleep on this one. Thanks! I think I might have a shot at
understanding this one in the morning.
Jeff C. (Guest)
on 2006-04-08 10:17
Nathan O. wrote:
> Austin Z. wrote:
>> No. To clarify my statement:
>>
>>   #attr_accessor creates a pair of instance methods that access and
>>   may instantiate an instance variable, but don't have to.
>>
>> Instance variables are always bound to a particular value of self. (I'm
>> not *quite* sure where class variables reside.)
>>
> ...
>>
>> "class Foo", "class << self", and "def myself" all change scope and the
>> meaning of "self" in that scope.
> Way, way over my head, but that probably has something to do with the
> two-year-old demanding that I stop reading and start wrestling with him.
> I'll sleep on this one. Thanks! I think I might have a shot at
> understanding this one in the morning.

As traditional as they are, for me the Foo/bar style examples can be
confusing because they give no context.

The Pickaxe book gives a good example of the difference between instance
variables and class variables and how they can be useful.  Perhaps this
is stuff you already know, but it can be helpful to cover it again.

In the Pickaxe example (paraphrasing the code), they're making a Jukebox
application which plays songs and records the total number of plays of
each song, as well as the total number of songs played by the jukebox.

class Song
  attr_accessor :name, :artist, :duration, :plays

  @@total_plays = 0   # class variable, the total number of all songs
played by the jukebox

  def initialize(name, duration)
    self.name = name               # using the accessor methods
    self.artist = artist           # using the accessor methods
    self.duration = duration       # using the accessor methods
    plays = 0                      # using the accessor methods
  end

  def play
    @@total_plays += 1    # increase the total count
    self.plays += 1       # increase the count for this song
    # play the song
  end
end

So if you do this:

so_what = Song.new("So What", "Miles Davis", 9.24)

so_what.play
so_what.play
Song.total_plays   #=>  2
so_what.plays      #=>  2

penny_lane = Song.new("Penny Lane", "The Beatles", 3.45)

penny_lane.play
penny_lane.play

Song.total_plays   #=> 4
penny_lane.plays   #=> 2

So the "@@total_plays" variable stores a value unique to the class of
Song, regardless of instances.  And the instance variables store values
unique to each instance.  The class variable can be "declared" or used
in the body of the class definition, but the instance variable should be
used in the body of a method.

I'm sure you know most of this, but hopefully it helps a bit.

Jeff C.man
Austin Z. (Guest)
on 2006-04-08 19:00
(Received via mailing list)
On 4/8/06, Jeff C.man <removed_email_address@domain.invalid> wrote:
>>> "class Foo", "class << self", and "def myself" all change scope and
>>> the meaning of "self" in that scope.
>> Way, way over my head, but that probably has something to do with the
>> two-year-old demanding that I stop reading and start wrestling with
>> him. I'll sleep on this one. Thanks! I think I might have a shot at
>> understanding this one in the morning.
> As traditional as they are, for me the Foo/bar style examples can be
> confusing because they give no context.

Fair enough. However, let me point out that you showed something
*different* than I showed. I deliberately didn't get into class
variables (@@var) because the point I was making was solely about the
change of scope, and @@var is a little funny with scope (I personally
think it's broken, and I simply don't use them any more).

In many ways, the Pickaxe Song/Jukebox example is bad anyway; the
*Jukebox* should be keeping track of how many songs it has played, not
the Song class, which may be used by other Jukebox instances, and for
billing purposes, you don't want those song counts commingled. :)

In your example, you also didn't give a definition for
Song::total_plays.

If, however, we were to accept the Pickaxe premise as valid, here's what
I would do:

  class Song
    attr_accessor :name
    attr_accessor :artist
    attr_accessor :duration
    attr_reader   :plays

    # Class instance variable
    @total_plays = 0

    class << self
      attr_reader :total_plays
    end

    # This could be in the class << self as def add_play...
    def self.add_play
      @total_plays += 1
    end

    def initialize(name, artist, duration)
      self.name = name
      self.artist = artist
      self.duration = duration
      @plays = 0
    end

    def play
      self.class.add_play
      @plays += 1
      # play the song
    end
  end

@total_plays in the "class Song" scope belongs to the self that *is*
"class Song". This is the same scope within "def self.add_play" or in
the method defined by "class << self; attr_reader :total_plays; end".

-austin
Jeff C. (Guest)
on 2006-04-09 01:39
Austin Z. wrote:
> .. a bunch of good stuff snipped ..

Thanks for your corrections, Austin, I see your points.

I certainly didn't mean to criticize your examples, I just felt like it
might help to bring the discussion to some concrete examples, as the
original poster seemed to have a confusion about the nature of class
versus instance variables, which IMO might be cleared up before the
higher-level discussion about scoping becomes useful.

Jeff
This topic is locked and can not be replied to.