Accessing class variables from the outside (beginner question)

I am still learning Ruby and I am trying to get something
like this to work and am unsure how.

I know I could do attr_reader to
access "ones" but ones might be an
array, hash, etc.

Is there a way to do something like this:
class Test
   def initialize
     @try["hashworld"] = 10000
     @ones = 1,2,3,4
   end
   def addit(one,two)
      #can code add one + two, from
      #inside and outside?
      return(one + two)
   end
end
tens = 10,20,30,40,50
a = Test.new
p a.addit(ones[1],tens[0]) #prints 12
p a.addit(tens[3],ones[0]) #prints 41
p a.addit(tens[3],try["hashworld"]) #prints 10040

Thanks,
Tom

Hi --

I am still learning Ruby and I am trying to get something
like this to work and am unsure how.

You don't have any class variables in your example, only instance
variables. Class variables look like this: @@var, and in most cases
aren't what you want to use anyway.

I know I could do attr_reader to access "ones" but ones might be an
array, hash, etc.

Is there a way to do something like this:
class Test
  def initialize
    @try["hashworld"] = 10000

@try is nil at this point; you can't index it.

    @ones = 1,2,3,4
  end
  def addit(one,two)
     #can code add one + two, from
     #inside and outside?
     return(one + two)
  end
end
tens = 10,20,30,40,50
a = Test.new

You'll get a fatal error at this point if you run this code.

p a.addit(ones[1],tens[0]) #prints 12
p a.addit(tens[3],ones[0]) #prints 41
p a.addit(tens[3],try["hashworld"]) #prints 10040

You haven't defined try. (It has no connection to the @try inside the
Test#initialize method, which you also haven't defined.)

I'm not sure exactly what you want to do but I think you're
overthinking it. Basically, instance variables (like @try) are visible
only to the object that owns them. If that object wants to expose them
to other objects, it has to provide methods for that purpose.
attr_reader is a macro that writes such a method for you, such that
this:

   attr_reader :ones

is the same as this:

   def ones
     @ones
   end

but shorter.

David

···

On Tue, 10 Jun 2008, progcat@comcast.net wrote:

--
Rails training from David A. Black and Ruby Power and Light:
   INTRO TO RAILS June 9-12 Berlin
   ADVANCING WITH RAILS June 16-19 Berlin
   ADVANCING WITH RAILS July 21-24 Edison, NJ
See http://www.rubypal.com for details and updates!

As first thing, variables like @try and @ones in your code are not class
variables, as the subject of your post implies, but instance variables. Class
variables are something else (their names start with @@, are shared among the
class object itself, its instances, derived class objects and their
instances).

Regarding your question. The only way to access instance variables from
outside the instance is to create accessor methods for them. You can do it
using attr_reader and similar, or you can write them by hand. For example:

class Test
  ...

  def ones
    @ones
  end

end

I hope this helps

Stefano

···

On Tuesday 10 June 2008, progcat@comcast.net wrote:

I am still learning Ruby and I am trying to get something
like this to work and am unsure how.

I know I could do attr_reader to
access "ones" but ones might be an
array, hash, etc.

Is there a way to do something like this:
class Test
   def initialize
     @try["hashworld"] = 10000
     @ones = 1,2,3,4
   end
   def addit(one,two)
      #can code add one + two, from
      #inside and outside?
      return(one + two)
   end
end
tens = 10,20,30,40,50
a = Test.new
p a.addit(ones[1],tens[0]) #prints 12
p a.addit(tens[3],ones[0]) #prints 41
p a.addit(tens[3],try["hashworld"]) #prints 10040

Thanks,
Tom

While probably true in this case, I think this statement is dangerously loaded... Your words have sway and affect design decisions. Sometimes class variables are exactly the right tool for the job:

% find */dev/{lib,test} -name \*.rb | xargs grep -l @@ | wc -l
       50

···

On Jun 9, 2008, at 22:15 , David A. Black wrote:

Class variables [...] in most cases aren't what you want to use anyway.

Hmm I do not know what to say, of course it is possible, but you are
probably right not talking about metaprogramming to a nuby ;).

···

On Tue, Jun 10, 2008 at 8:11 AM, Stefano Crocco <stefano.crocco@alice.it> wrote:

Regarding your question. The only way to access instance variables from
outside the instance is to create accessor methods for them.

--
http://ruby-smalltalk.blogspot.com/

---
As simple as possible, but not simpler.
Albert Einstein

Sometimes class variables are exactly the right tool for the job

Where would you recommend using class variables over class level
instance variables?

Class variables [...] in most cases aren't what you want to use anyway.

While probably true in this case, I think this statement is dangerously
loaded... Your words have sway and affect design decisions. Sometimes class
variables are exactly the right tool for the job:

% find */dev/{lib,test} -name \*.rb | xargs grep -l @@ | wc -l
     50

May I suggest to trust David more than grep ;). I do not know of any
usecase where class variables are the *right* thing to use, but I am
eager to learn, so please enlighten me.

Cheers
Robert

···

On Tue, Jun 10, 2008 at 9:16 AM, Ryan Davis <ryand-ruby@zenspider.com> wrote:

On Jun 9, 2008, at 22:15 , David A. Black wrote:

--
http://ruby-smalltalk.blogspot.com/

---
As simple as possible, but not simpler.
Albert Einstein

Of course, you're right. I meant: the normal way to access instance variables
from the outside is to create accessor methods for them. There are other ways,
for example the instance_variable_set and instance_variable_get methods, but
they should be used only when in special cases.

Stefano

···

On Tuesday 10 June 2008, Robert Dober wrote:

On Tue, Jun 10, 2008 at 8:11 AM, Stefano Crocco <stefano.crocco@alice.it> wrote:
> Regarding your question. The only way to access instance variables from
> outside the instance is to create accessor methods for them.

Hmm I do not know what to say, of course it is possible, but you are
probably right not talking about metaprogramming to a nuby ;).

if you want a variable available to all instances that says how many
instances exist. If you want to create an ID that increments with
each instance. If you are storing a path that may change, but all
instances will use it. If you want to update scaling criteria on
several objects at once, having a class variable set to twips, pixels,
or inches could be just the right tool. And on and on and on......

···

On Jun 10, 4:14 am, Paul McMahon <p...@ubit.com> wrote:

> Sometimes class variables are exactly the right tool for the job

Where would you recommend using class variables over class level
instance variables?

that is a grep on MY code... I trust my code more than I trust your trust. :stuck_out_tongue:

···

On Jun 10, 2008, at 05:01 , Robert Dober wrote:

On Tue, Jun 10, 2008 at 9:16 AM, Ryan Davis <ryand- > ruby@zenspider.com> wrote:

On Jun 9, 2008, at 22:15 , David A. Black wrote:

Class variables [...] in most cases aren't what you want to use anyway.

While probably true in this case, I think this statement is dangerously
loaded... Your words have sway and affect design decisions. Sometimes class
variables are exactly the right tool for the job:

% find */dev/{lib,test} -name \*.rb | xargs grep -l @@ | wc -l
    50

May I suggest to trust David more than grep ;). I do not know of any
usecase where class variables are the *right* thing to use, but I am
eager to learn, so please enlighten me.

Hi --

···

On Wed, 11 Jun 2008, Ryan Davis wrote:

On Jun 10, 2008, at 05:01 , Robert Dober wrote:

On Tue, Jun 10, 2008 at 9:16 AM, Ryan Davis <ryand-ruby@zenspider.com> >> wrote:

On Jun 9, 2008, at 22:15 , David A. Black wrote:

Class variables [...] in most cases aren't what you want to use anyway.

While probably true in this case, I think this statement is dangerously
loaded... Your words have sway and affect design decisions. Sometimes class
variables are exactly the right tool for the job:

% find */dev/{lib,test} -name \*.rb | xargs grep -l @@ | wc -l
   50

May I suggest to trust David more than grep ;). I do not know of any
usecase where class variables are the *right* thing to use, but I am
eager to learn, so please enlighten me.

that is a grep on MY code... I trust my code more than I trust your trust. :stuck_out_tongue:

Also, I'm not saying that there are no uses for class variables. And
grep is our friend; it's how we demonstrate, for example, that
camelCase variable names are virtually unheard of :slight_smile: I'll stand by my
"in most cases", though, with regard to class variables.

David

--
Rails training from David A. Black and Ruby Power and Light:
   INTRO TO RAILS June 9-12 Berlin
   ADVANCING WITH RAILS June 16-19 Berlin
   ADVANCING WITH RAILS July 21-24 Edison, NJ
See http://www.rubypal.com for details and updates!

if you want a variable available to all instances that says how many
instances exist. If you want to create an ID that increments with
each instance. If you are storing a path that may change, but all
instances will use it. If you want to update scaling criteria on
several objects at once, having a class variable set to twips, pixels,
or inches could be just the right tool. And on and on and on......

Perhaps I wasn't clear enough. As far as I know, you can accomplish all
that using class level instance variables. For example, consider the
following code:

class ClassLevelVariables
  @instance_count = 0
  class << self
    attr_accessor :instance_count
  end

  def initialize
    ClassLevelVariables.instance_count += 1
  end
end

class ClassVariables
  @@instance_count = 0
  class << self
    def instance_count
      @@instance_count
    end
  end

  def initialize
    @@instance_count += 1
  end
end

[ClassLevelVariables, ClassVariables].each do |klass|
  puts klass.instance_count
  klass.new
  puts klass.instance_count
end

The code is almost equivalent, and I was just wondering when one style
is prefered over the other.