Forum: Ruby Class Level Variables

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.
Cory (Guest)
on 2007-04-30 04:04
Alright, I'm missing some core ruby concept here that I just can't
figure out; any assistance would be excellent and welcome:

Long story short, I'm attempting to modify class level variables @@foo,
@@bar from an action in a ruby controller (an instance of a given
controller).

It seems that the class level variables set just fine...however, the
next time the action is invoked, they're nil again.

Code here: http://rafb.net/p/U3Q9VC20.html
Ari B. (Guest)
on 2007-04-30 04:36
(Received via mailing list)
On Apr 29, 2007, at 8:04 PM, Cory wrote:
<snip>

newbie question pertaining  to class level variables:

What's the difference between @foo and @@foo? Is there even a
difference?

---------------------------------------------------------------|
~Ari
"I don't suffer from insanity. I enjoy every minute of it" --1337est
man alive
zswu (Guest)
on 2007-04-30 04:44
(Received via mailing list)
If you know C++.

@foo seams look link a normal member variable , i.e. private TYPE foo
@@foo seams look link a static member variable, i.e. static TYPE foo

Initialize the class variable in the constroctor is a good idea.
That's will make the class variable valide all of the class.
class xxx
    def initialize
        @@foo = XXXXX
    end
end
unknown (Guest)
on 2007-04-30 04:48
(Received via mailing list)
In message <removed_email_address@domain.invalid>, Ari
Brown writes:
>newbie question pertaining  to class level variables:

>What's the difference between @foo and @@foo? Is there even a
>difference?

@foo = instance variable; each instance has one
@@foo = class variable; only one shared among all class members

  class Example
    def print
      puts @y, @@z
    end
    def initialize(x)
      @y = x
      @@z = x
    end
  end
  e1 = Example.new(1)
  e2 = Example.new(2)
  e1.print
  e2.print

The first print prints 1 and 2, the second prints 2 and 2.  The first
new sets e1.y to 1, and Example.z to 1.  The second sets e2.y to 2,
and Example.z to 2.  There's only one @@z (also called "Example.z"), but
there's one @y for each instance.

-s
Gregory B. (Guest)
on 2007-04-30 05:00
(Received via mailing list)
On 4/29/07, Ari B. <removed_email_address@domain.invalid> wrote:
>
> On Apr 29, 2007, at 8:04 PM, Cory wrote:
> <snip>
>
> newbie question pertaining  to class level variables:
>
> What's the difference between @foo and @@foo? Is there even a
> difference?

I wrote a newbie oriented post on this a while ago.
Hope it helps...

http://www.oreillynet.com/ruby/blog/2007/01/nubyge...
Gregory B. (Guest)
on 2007-04-30 05:03
(Received via mailing list)
On 4/29/07, zswu <removed_email_address@domain.invalid> wrote:
>     end
> end

Please don't do this.  That assignment would happen every time you
create an instance of the object, which completely defeats the purpose
of class level variables. (Whether you use class instance variables or
class variables).

Class level variables are shared by all your instances.
Gregory B. (Guest)
on 2007-04-30 05:05
(Received via mailing list)
On 4/29/07, Cory <removed_email_address@domain.invalid> wrote:
> Alright, I'm missing some core ruby concept here that I just can't
> figure out; any assistance would be excellent and welcome:
>
> Long story short, I'm attempting to modify class level variables @@foo,
> @@bar from an action in a ruby controller (an instance of a given
> controller).

There is no such thing as a Ruby controller.  I think you may actually
be asking a question about Ruby on Rails, so please use the rails
mailing list.

warm regards,
-gregory.
zswu (Guest)
on 2007-04-30 05:21
(Received via mailing list)
Huuuum, you are right.
Cory W. (Guest)
on 2007-04-30 05:25
Gregory B. wrote:
> On 4/29/07, Cory <removed_email_address@domain.invalid> wrote:
>> Alright, I'm missing some core ruby concept here that I just can't
>> figure out; any assistance would be excellent and welcome:
>>
>> Long story short, I'm attempting to modify class level variables @@foo,
>> @@bar from an action in a ruby controller (an instance of a given
>> controller).
>
> There is no such thing as a Ruby controller.  I think you may actually
> be asking a question about Ruby on Rails, so please use the rails
> mailing list.
>
> warm regards,
> -gregory.

You're right - it's a rails controller; but it's a ruby question.
Apparently my question has now been hijacked and we're now discussing
the difference between class level variables and instance level
variables.

Every test I've cooked out simply won't allow me to maintain state in a
class level variable set from an instance level context.  That's the
core of the question.
Gary W. (Guest)
on 2007-04-30 05:32
(Received via mailing list)
On Apr 29, 2007, at 8:44 PM, zswu wrote:

> If you know C++.
>
> @foo seams look link a normal member variable , i.e. private TYPE foo
> @@foo seams look link a static member variable, i.e. static TYPE foo

I think a lot of confusion about Ruby class variables comes from
trying to compare them to similarly named constructs in other languages.

There is also a tendency to think class variables are like instance
variables because @@ is like @.  Again, you'll be mislead by that
assumption.

1) Class variables are lexically scoped.  They are *not* associated
    with the object identified by 'self' but instead by the innermost
    class block:

class B;end
class A
   @@foo = 42    # @@foo for A
   def foo
     @@foo       # @@foo for A
   end
   def B.foo
     @@foo       # self is B but @@foo is for A
   end
end

puts A.new.foo  # 42
puts B.foo      # 42

This lexical scoping is really important to understand when you
start using singleton class blocks, class_eval, module_eval,
or define_method, since the these constructs don't introduce a lexical
scope:

class X
   @@foo = 42
   class Y
     @@foo = 43
     X.class_eval {
        puts @@foo    # 43, this is Y's @@foo, not X's @@foo
     }
   end
end

2) Class variables are associated with a class *and* its subclasses
and the order of initialization is important.

class C
   @@foo = 42        # shared by C and its decendents!
   def foo
     @@foo           # shared with C, D, and E
   end
   def bar
     @@bar           # this is C's @@bar
   end
end

class D < C
end

class E < C
   @@foo = 43        # @@foo shared with C, D, and E
   @@bar = 44        # @@bar only defined for E
   def bar
     @@bar           # this is E's @@bar
   end
end

puts D.new.foo       # 43

puts E.new.bar       # 44
puts C.new.bar       # undefined!

class C
   @@bar = 45
end

puts C.new.bar       # 45
puts E.new.bar       # still 44


> Initialize the class variable in the constroctor is a good idea.
> That's will make the class variable valide all of the class.
> class xxx
>    def initialize
>        @@foo = XXXXX
>    end
> end

This is a really bad idea.  Every time you create a new instance,
you'll reset the class variable.


Gary W.
Cory W. (Guest)
on 2007-04-30 05:45
Cory wrote:
> Alright, I'm missing some core ruby concept here that I just can't
> figure out; any assistance would be excellent and welcome:
>
> Long story short, I'm attempting to modify class level variables @@foo,
> @@bar from an action in a ruby controller (an instance of a given
> controller).
>
> It seems that the class level variables set just fine...however, the
> next time the action is invoked, they're nil again.
>
> Code here: http://rafb.net/p/U3Q9VC20.html

It just struck me - it likely is a rails issue, I'm running in
development mode and methinks it's likely reloading the class every
single time.

And - sorry if I seemed snippy, been fighting this for a while.
Gregory B. (Guest)
on 2007-04-30 05:58
(Received via mailing list)
On 4/29/07, Cory W. <removed_email_address@domain.invalid> wrote:
> >
> > Code here: http://rafb.net/p/U3Q9VC20.html
>
> It just struck me - it likely is a rails issue, I'm running in
> development mode and methinks it's likely reloading the class every
> single time.
>
> And - sorry if I seemed snippy, been fighting this for a while.

As far as I know, it's a rails issue period.  Unless you're storing
something in the database(either via sessions or models), you don't
have state preservation.  I don't know enough about Rails to give you
the information you need about that, others on this list do.

However, the best place to ask this is certainly the Rails list.
Cory W. (Guest)
on 2007-04-30 06:04
Gregory B. wrote:
> On 4/29/07, Cory W. <removed_email_address@domain.invalid> wrote:
>> >
>> > Code here: http://rafb.net/p/U3Q9VC20.html
>>
>> It just struck me - it likely is a rails issue, I'm running in
>> development mode and methinks it's likely reloading the class every
>> single time.
>>
>> And - sorry if I seemed snippy, been fighting this for a while.
>
> As far as I know, it's a rails issue period.  Unless you're storing
> something in the database(either via sessions or models), you don't
> have state preservation.  I don't know enough about Rails to give you
> the information you need about that, others on this list do.
>
> However, the best place to ask this is certainly the Rails list.

+1 for Greg.  It was an environment issue - meaning, when you're running
rails in development mode; you get continual class reloading; thusly -
no 'state' at the class level.

I'll head there next time.  Thanks for listening folks.
Rick D. (Guest)
on 2007-04-30 06:13
(Received via mailing list)
On 4/29/07, Cory W. <removed_email_address@domain.invalid> wrote:

> +1 for Greg.  It was an environment issue - meaning, when you're running
> rails in development mode; you get continual class reloading; thusly -
> no 'state' at the class level.

And don't count on persistence in the production environment either.
For one thing, it's likely that the deployment will eventually end up
using something like mongrel_cluster, so each instance of the runtime
will have it's own state, except for that shared through external
means such as the database.

--
Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/
Ari B. (Guest)
on 2007-04-30 06:22
(Received via mailing list)
On Apr 29, 2007, at 9:03 PM, Gregory B. wrote:
<snip>

> Please don't do this.  That assignment would happen every time you
> create an instance of the object, which completely defeats the purpose
> of class level variables. (Whether you use class instance variables or
> class variables).

So use @@foo for general ideas (like @@foo = {} and when used in some
file.open(path, 'r') do ..... command) and @foo for variables that
hold specific values?

Got it.

P.S. = Is there some site that has a bunch of secrets that everyone
(but me) knows in making your Ruby code look like Ruby?

~ Ari
English is like a pseudo-random number generator - there are a
bajillion rules to it, but nobody cares.
Gregory B. (Guest)
on 2007-04-30 07:22
(Received via mailing list)
On 4/29/07, Ari B. <removed_email_address@domain.invalid> wrote:
> file.open(path, 'r') do ..... command) and @foo for variables that
> hold specific values?

Don't use @@foo, ever.  Unless you know *why* you want to.  They add
unnecessary confusion.  Instead, use class instance variables.
Robert D. (Guest)
on 2007-04-30 09:53
(Received via mailing list)
On 4/30/07, Gregory B. <removed_email_address@domain.invalid> wrote:
> > So use @@foo for general ideas (like @@foo = {} and when used in some
> > file.open(path, 'r') do ..... command) and @foo for variables that
> > hold specific values?
>
> Don't use @@foo, ever.  Unless you know *why* you want to.  They add
> unnecessary confusion.  Instead, use class instance variables.

Could not agree more with you, however, I would not dare stating this
as a *General Rule of Conduct*.
Will @@class_iv go away? I do not think so.

Cheers
Robert
Gregory B. (Guest)
on 2007-04-30 17:23
(Received via mailing list)
On 4/30/07, Robert D. <removed_email_address@domain.invalid> wrote:
> On 4/30/07, Gregory B. <removed_email_address@domain.invalid> wrote:

> > Don't use @@foo, ever.  ___Unless you know *why* you want to___.  They add

emp added

> Could not agree more with you, however, I would not dare stating this
> as a *General Rule of Conduct*.
> Will @@class_iv go away? I do not think so.

I agree with you that it can't be just  a rule.  Ruby 1.9 fixes some
issues with them though, so it'll be less scary there...

I'm still waiting for the killer use case that justifies them...
German Monfort (Guest)
on 2007-04-30 21:53
(Received via mailing list)
>    end
>    end
>
> puts C.new.bar       # 45
> puts E.new.bar       # still 44
>
> Gary W.
Shouldn't be
puts D.new.foo       # 42 ?

Because D < C and has no foo method defined (so it uses C' foo) and also
has
no @@foo defined (so it uses C's @@foo) which is set to 42 not 43.
I'm confused here.
Gary W. (Guest)
on 2007-04-30 23:16
(Received via mailing list)
On Apr 30, 2007, at 1:52 PM, German Monfort wrote:

>>    end
>>    end
>>
> I'm confused here.
I was illustrating the fact that C and E don't share the same @@bar
due to
initialization order and the location of the definitions of C.bar and
E.bar.

If you called D.new.foo you would get 43 because @@foo is shared by
C, D, and E
and was updated to reference 43 in the class block that defined E.

If you called D.new.bar you would get 45 because the call to 'bar'
would be
implemented by the definition in C where @@bar refers to C's @@bar.
This is
a good example of how class variables are not relative to self!

Gary W.
Ari B. (Guest)
on 2007-05-01 02:59
(Received via mailing list)
On Apr 29, 2007, at 11:21 PM, Gregory B. wrote:
<snip>
>
> Don't use @@foo, ever.  Unless you know *why* you want to.  They add
> unnecessary confusion.  Instead, use class instance variables.

Sounds like a good rule to me

--------------------------------------------|
If you're not living on the edge,
then you're just wasting space.
German Monfort (Guest)
on 2007-05-01 05:33
(Received via mailing list)
El Lunes, 30 de Abril de 2007 19:15, Gary W.
escribió:> >>      @@bar           # this is C's @@bar
> >>      @@bar           # this is E's @@bar
> >> end
> > also has
> and was updated to reference 43 in the class block that defined E.
>
> If you called D.new.bar you would get 45 because the call to 'bar'
> would be
> implemented by the definition in C where @@bar refers to C's @@bar.
> This is
> a good example of how class variables are not relative to self!
>
> Gary W.

OK, I now understand the difference.

Probably I'm too new to programming to understand the full power of
class
variables, and I found this concept a little bit dangerous because you
can
affect the whole behavior of a class by simply changing a class variable
in
any other subclass ... so I try not to use class variables for noiw.

I still need to read more and more :D

Thanks Gary
Gary W. (Guest)
on 2007-05-01 07:11
(Received via mailing list)
On Apr 30, 2007, at 9:32 PM, German Monfort wrote:
> OK, I now understand the difference.
>
> Probably I'm too new to programming to understand the full power of
> class
> variables, and I found this concept a little bit dangerous because
> you can
> affect the whole behavior of a class by simply changing a class
> variable in
> any other subclass ... so I try not to use class variables for noiw.

Well Ruby's class variables are unusual in their semantics, even veteran
programmers get confused by them.

The usual recommendation is to use 'class instance variables' when you
want to have state associated with a particular class object (vs. a
class hierarchy.)  The easiest way to do that is to create attributes
via the singleton class:

class A
   class <<self
     attr_accessor :alpha
   end
end

class B < A
end

A.alpha = 4
puts A.alpha    # 4

puts B.alpha    # nil
B.alpha = 5
puts B.alpha            # 5

puts A.alpha            # 4

In this way you define the accessor once but the state is unique to each
class and to each subclass.


Gary W.
This topic is locked and can not be replied to.