Quick syntax question

Consider the following three class definitions:

class Foo
  def self.bar
    @@bar
  end
  def self.bar=(val)
    @@bar = val
  end
end

class Foo
  class << self
    def bar
      @@bar
    end
    def bar=(val)
      @@bar = val
    end
  end
end

class Foo
  class << self
    attr_accessor :bar
  end
end

Am I correct in believing that they are equivalent? If not, how do they
differ?

--Greg

Yes, semantically anyway. (I remember seeing somewhere that attr_accessor has some performance tricks, but the effect is the same)

···

On Apr 10, 2006, at 11:00 AM, Gregory Seidman wrote:

Am I correct in believing that they are equivalent? If not, how do they
differ?

They are not equivalent. The first two are the same, but the third
will be accessing @bar, not @@bar. (Try it in IRB and you'll see.)

-austin

···

On 4/10/06, Gregory Seidman <gsslist+ruby@anthropohedron.net> wrote:

Consider the following three class definitions:

class Foo
  def self.bar
    @@bar
  end
  def self.bar=(val)
    @@bar = val
  end
end

class Foo
  class << self
    def bar
      @@bar
    end
    def bar=(val)
      @@bar = val
    end
  end
end

class Foo
  class << self
    attr_accessor :bar
  end
end

Am I correct in believing that they are equivalent? If not, how do they
differ?

--
Austin Ziegler * halostatue@gmail.com
               * Alternate: austin@halostatue.ca

Oops, my eyes musta glazed over the double @-signs. Austin is correct.

···

On Apr 10, 2006, at 11:24 AM, Austin Ziegler wrote:

They are not equivalent. The first two are the same, but the third
will be accessing @bar, not @@bar. (Try it in IRB and you'll see.)

> Consider the following three class definitions:
>
> class Foo
> def self.bar
> @@bar
> end
> def self.bar=(val)
> @@bar = val
> end
> end
>
> class Foo
> class << self
> def bar
> @@bar
> end
> def bar=(val)
> @@bar = val
> end
> end
> end
>

[different third class deleted]

> Am I correct in believing that they are equivalent? If not, how do they
> differ?

They are not equivalent. The first two are the same, but the third
will be accessing @bar, not @@bar. (Try it in IRB and you'll see.)

Interestingly though, the the sexps representing the AST for the first two
classes are pretty different looking:

[[:class,
  :Example,
  :Object,
  [:defn,
   :example,
   [:scope,
    [:block,
     [:args],
     [:defs, [:self], :bar, [:scope, [:block, [:args], [:cvar, :@@bar]]]],
     [:defs,
      [:self],
      :bar=,
      [:scope, [:block, [:args, :val], [:cvasgn, :@@bar, [:lvar, :val]]]]]]]]]

vs.

[[:class,
  :Example,
  :Object,
  [:defn,
   :example,
   [:scope,
    [:block,
     [:args],
     [:sclass,
      [:self],
      [:scope,
       [:block,
        [:defn, :bar, [:scope, [:block, [:args], [:cvar, :@@bar]]]],
        [:defn,
         :bar=,
         [:scope,
          [:block, [:args, :val], [:cvasgn, :@@bar, [:lvar, :val]]]]]]]]]]]]]

···

On 4/10/06, Austin Ziegler <halostatue@gmail.com> wrote:

On 4/10/06, Gregory Seidman <gsslist+ruby@anthropohedron.net> wrote:

-austin
--
Austin Ziegler * halostatue@gmail.com
               * Alternate: austin@halostatue.ca

--
thanks,
-pate
-------------------------

> Consider the following three class definitions:
>
> class Foo
> def self.bar
> @@bar
> end
> def self.bar=(val)
> @@bar = val
> end
> end
>
> class Foo
> class << self
> def bar
> @@bar
> end
> def bar=(val)
> @@bar = val
> end
> end
> end
>
> class Foo
> class << self
> attr_accessor :bar
> end
> end
>
> Am I correct in believing that they are equivalent? If not, how do they
> differ?

They are not equivalent. The first two are the same,

That's good to know. I can't see any reason to prefer the second over
the first. It's a lot more noisy.

···

On 4/10/06, Austin Ziegler <halostatue@gmail.com> wrote:

On 4/10/06, Gregory Seidman <gsslist+ruby@anthropohedron.net> wrote:

but the third
will be accessing @bar, not @@bar. (Try it in IRB and you'll see.)

--
R. Mark Volkmann
Object Computing, Inc.

When you're defining a lot of class methods, class << self makes
sense. One or two? Then you may as well use def self.foo if you can.

-austin

···

On 4/10/06, Mark Volkmann <r.mark.volkmann@gmail.com> wrote:

That's good to know. I can't see any reason to prefer the second over
the first. It's a lot more noisy.

--
Austin Ziegler * halostatue@gmail.com
               * Alternate: austin@halostatue.ca

Hi --

Consider the following three class definitions:

class Foo
  def self.bar
    @@bar
  end
  def self.bar=(val)
    @@bar = val
  end
end

class Foo
  class << self
    def bar
      @@bar
    end
    def bar=(val)
      @@bar = val
    end
  end
end

class Foo
  class << self
    attr_accessor :bar
  end
end

Am I correct in believing that they are equivalent? If not, how do they
differ?

They are not equivalent. The first two are the same,

That's good to know. I can't see any reason to prefer the second over
the first. It's a lot more noisy.

There's a subtle difference between the two ways of defining a
singleton method, though:

X = 1

class C
end

class << C
   X = 2
end

class << C
   def x
     X
   end
end

def C.x2
   X
end

p C.x # 2 (the X from C's singleton class)
p C.x2 # 1 (the X from outer scope)

David

···

On Tue, 11 Apr 2006, Mark Volkmann wrote:

On 4/10/06, Austin Ziegler <halostatue@gmail.com> wrote:

On 4/10/06, Gregory Seidman <gsslist+ruby@anthropohedron.net> wrote:

--
David A. Black (dblack@wobblini.net)
Ruby Power and Light, LLC (http://www.rubypowerandlight.com)

"Ruby for Rails" coming in PDF April 15, and in paper May 1!

class C
   class << self # 100% class stuff that is hard to do with 'Class.' below

     def a_class_method() end

     alias one_class_method to_another

     define_method('another_class_method'){ 42 }

     %w( a b c d e f g ).each{|of_seven_class_attributes| attr of_seven_class_attributes}

     undef a_blown_away_class_method

     remove_method 'blow_this_method_of_off_the_class'

     undef_method 'stop_responding_to_this_class_method_at_all'

     public 'a' # the class method
   end
end

'class << self' is 100 time more consistent and, as soon as you break one
method 100 times less noisy imho.

regards.

-a

···

On Tue, 11 Apr 2006, Mark Volkmann wrote:

On 4/10/06, Austin Ziegler <halostatue@gmail.com> wrote:

On 4/10/06, Gregory Seidman <gsslist+ruby@anthropohedron.net> wrote:

Consider the following three class definitions:

class Foo
  def self.bar
    @@bar
  end
  def self.bar=(val)
    @@bar = val
  end
end

class Foo
  class << self
    def bar
      @@bar
    end
    def bar=(val)
      @@bar = val
    end
  end
end

class Foo
  class << self
    attr_accessor :bar
  end
end

Am I correct in believing that they are equivalent? If not, how do they
differ?

They are not equivalent. The first two are the same,

That's good to know. I can't see any reason to prefer the second over
the first. It's a lot more noisy.

--
be kind whenever possible... it is always possible.
- h.h. the 14th dali lama

Just expressing personal preference ... even in that case I prefer the
first form (using self. on each class method). That way when I look at
a method, it's immediate obvious that it's a class method if the name
starts with "self.". Otherwise I have to lookup upward in the code to
see if the method is contained in a "class << self"

···

On 4/10/06, Austin Ziegler <halostatue@gmail.com> wrote:

On 4/10/06, Mark Volkmann <r.mark.volkmann@gmail.com> wrote:
> That's good to know. I can't see any reason to prefer the second over
> the first. It's a lot more noisy.

When you're defining a lot of class methods, class << self makes
sense. One or two? Then you may as well use def self.foo if you can.

--
R. Mark Volkmann
Object Computing, Inc.

Hi --

Consider the following three class definitions:

class Foo
  def self.bar
    @@bar
  end
  def self.bar=(val)
    @@bar = val
  end
end

class Foo
  class << self
    def bar
      @@bar
    end
    def bar=(val)
      @@bar = val
    end
  end
end

class Foo
  class << self
    attr_accessor :bar
  end
end

Am I correct in believing that they are equivalent? If not, how do they
differ?

They are not equivalent. The first two are the same,

That's good to know. I can't see any reason to prefer the second over
the first. It's a lot more noisy.

class C
class << self # 100% class stuff that is hard to do with 'Class.' below

   def a_class_method() end

   alias one_class_method to_another

   define_method('another_class_method'){ 42 }

   %w( a b c d e f g ).each{|of_seven_class_attributes| attr of_seven_class_attributes}

   undef a_blown_away_class_method

   remove_method 'blow_this_method_of_off_the_class'

   undef_method 'stop_responding_to_this_class_method_at_all'

   public 'a' # the class method

and:

     self

:slight_smile:

end
end

'class << self' is 100 time more consistent and, as soon as you break one
method 100 times less noisy imho.

David

···

On Tue, 11 Apr 2006, ara.t.howard@noaa.gov wrote:

On Tue, 11 Apr 2006, Mark Volkmann wrote:

On 4/10/06, Austin Ziegler <halostatue@gmail.com> wrote:

On 4/10/06, Gregory Seidman <gsslist+ruby@anthropohedron.net> wrote:

--
David A. Black (dblack@wobblini.net)
Ruby Power and Light, LLC (http://www.rubypowerandlight.com)

"Ruby for Rails" coming in PDF April 15, and in paper May 1!

Thanks Ara! I was only thinking about defining class methods. You
gave me lots to consider that I wasn't before.

I do think it's a weird syntax though. It's a class definition inside
a class definition, but it isn't defining a nested class like many
Ruby beginners might guess at first glance.

···

On 4/10/06, ara.t.howard@noaa.gov <ara.t.howard@noaa.gov> wrote:

On Tue, 11 Apr 2006, Mark Volkmann wrote:

> On 4/10/06, Austin Ziegler <halostatue@gmail.com> wrote:
>> On 4/10/06, Gregory Seidman <gsslist+ruby@anthropohedron.net> wrote:
>>> Consider the following three class definitions:
>>>
>>> class Foo
>>> def self.bar
>>> @@bar
>>> end
>>> def self.bar=(val)
>>> @@bar = val
>>> end
>>> end
>>>
>>> class Foo
>>> class << self
>>> def bar
>>> @@bar
>>> end
>>> def bar=(val)
>>> @@bar = val
>>> end
>>> end
>>> end
>>>
>>> class Foo
>>> class << self
>>> attr_accessor :bar
>>> end
>>> end
>>>
>>> Am I correct in believing that they are equivalent? If not, how do they
>>> differ?
>>
>> They are not equivalent. The first two are the same,
>
> That's good to know. I can't see any reason to prefer the second over
> the first. It's a lot more noisy.

class C
   class << self # 100% class stuff that is hard to do with 'Class.' below

     def a_class_method() end

     alias one_class_method to_another

     define_method('another_class_method'){ 42 }

     %w( a b c d e f g ).each{|of_seven_class_attributes| attr of_seven_class_attributes}

     undef a_blown_away_class_method

     remove_method 'blow_this_method_of_off_the_class'

     undef_method 'stop_responding_to_this_class_method_at_all'

     public 'a' # the class method
   end
end

'class << self' is 100 time more consistent and, as soon as you break one
method 100 times less noisy imho.

--
R. Mark Volkmann
Object Computing, Inc.

yeah. no one said it wasn't weird :wink:

i've come to think of

   'class << self'

as

   'append to my class'

if that helps any.

cheers.

-a

···

On Tue, 11 Apr 2006, Mark Volkmann wrote:

Thanks Ara! I was only thinking about defining class methods. You gave me
lots to consider that I wasn't before.

I do think it's a weird syntax though. It's a class definition inside a
class definition, but it isn't defining a nested class like many Ruby
beginners might guess at first glance.

--
be kind whenever possible... it is always possible.
- h.h. the 14th dali lama

I'm new to Ruby and I'd like to be able to derive from a class and define a new class variable to replace a class variable in the parent class -- however I also want the original class to have access to it's original class variable.

Here's my simple test program:

class Klass
  cattr_accessor :prefix
   @@prefix = ''
   def Klass.show(string)
     puts @@prefix + string
   end
end

class DerivedKlass < Klass
   cattr_accessor :prefix
   @@prefix = ''
end

Klass.prefix = "123"
Klass.show("abc") # => "123abc"
DerivedKlass.prefix = "789"
DerivedKlass.show("abc")# => "789abc"
Klass.show("abc") # => "789abc"

I'd like Klass.show("abc") to instead produce "123abc".

The reason I'd think I'd like to do it this way is that I need to change how ActiveRecord works. Here's my problem:

I have 2 different ActiveRecord connections open and one of them is to a shared database so I set the following class variable:

ActiveRecord::Base.table_name_prefix = 'myapp_'

So while I refer to the table 'users' in my code in the database the table is actually named 'myapp_users'.

However the other connection is to a legacy database and I need to access the tables in this database without the table_name_prefix.

If this can't be done perhaps I could do something in DerivedKlass so that any accesses to it's actual or inherited object methods save Klass.prefix, replace it, and restore it? Of course the restoration would have to work for both normal program flow and for an error. This sounds uglier to me.

Thanks for any advice.

···

--
- Stephen Bannasch
   Concord Consortium, http://www.concord.org

Hi --

···

On Tue, 11 Apr 2006, ara.t.howard@noaa.gov wrote:

On Tue, 11 Apr 2006, Mark Volkmann wrote:

Thanks Ara! I was only thinking about defining class methods. You gave me
lots to consider that I wasn't before.

I do think it's a weird syntax though. It's a class definition inside a
class definition, but it isn't defining a nested class like many Ruby
beginners might guess at first glance.

yeah. no one said it wasn't weird :wink:

i've come to think of

'class << self'

as

'append to my class'

if that helps any.

Interesting -- I think of the << as associating the other way :slight_smile:

class << obj # yank the singleton class out of obj

David

--
David A. Black (dblack@wobblini.net)
Ruby Power and Light, LLC (http://www.rubypowerandlight.com)

"Ruby for Rails" coming in PDF April 15, and in paper May 1!

I realized after working more that cattr_accessor was defined in the core extensions in ActiveSupport as an extension of the class Class. I now working on understanding how this works:

# Extends the class object with class and instance accessors for class attributes,
# just like the native attr* accessors for instance attributes.
class Class # :nodoc:
   def cattr_reader(*syms)
     syms.flatten.each do |sym|
       class_eval(<<-EOS, __FILE__, __LINE__)
         unless defined? @@#{sym}
           @@#{sym} = nil
         end

         def self.#{sym}
           @@#{sym}
         end

         def #{sym}
           @@#{sym}
         end
       EOS
     end
   end

   def cattr_writer(*syms)
     syms.flatten.each do |sym|
       class_eval(<<-EOS, __FILE__, __LINE__)
         unless defined? @@#{sym}
           @@#{sym} = nil
         end

         def self.#{sym}=(obj)
           @@#{sym} = obj
         end

         def #{sym}=(obj)
           @@#{sym} = obj
         end
       EOS
     end
   end

···

--
- Stephen Bannasch
   Concord Consortium, http://www.concord.org

Here's a copy of my test case without using the ActiveSuppoprt's cattr_accessor method:

class Klass
   def prefix
     @@prefix
   end
   def prefix=(value)
     @@prefix=value
   end
   def Klass.show(string)
     puts @@prefix + string
   end
end

puts Klass.prefix.object_id

class DerivedKlass < Klass
   def prefix
     @@prefix
   end
   def prefix=(value)
     @@prefix=value
   end
end

puts DerivedKlass.prefix.object_id

Klass.prefix = "123"
Klass.show("abc") # => "123abc"
DerivedKlass.prefix = "789"
DerivedKlass.show("abc")# => "789abc"
Klass.show("abc") # => "789abc"

which produces:

2968188
123abc
789abc

I'd like to be able to create a class variable that will apply to all objects made from that class and ALSO create a derived class with a different class variable that is used in objects created from the derived class WITHOUT affecting the class variable defined in the original class.

It isn't obvious to me how to do this using class variables so either I'm missing something or there is another way to solve this programming problem. I'm going to look into how Ruby creates class variables.

···

--
- Stephen Bannasch
   Concord Consortium, http://www.concord.org

Stephen Bannasch wrote:

I'd like to be able to create a class variable that will apply to all
objects made from that class and ALSO create a derived class with a
different class variable that is used in objects created from the
derived class WITHOUT affecting the class variable defined in the
original class.

Try a class instance variable vs a class variable:

class C
    @somevar = 'x'
    class << C
        def somevar
            @somevar
        end

        def somevar=(var)
            @somevar=var
        end
    end
end

Its not as easily accessible as a class variable (only accessible from
class methods) and you'd have to initialize it to something in derived
classes (otherwise it's nil) but its non-inherited. Not totally what you
want, but maybe it'll help.

Andrew

···

--
Posted via http://www.ruby-forum.com/\.

this is one of the things traits.rb solves:

   harp:~ > yes | sudo gem install traits.rb > /dev/null 2>&1

   harp:~ > cat a.rb
   require 'traits'

   class Base
     class_trait 'a' => 42
   end

   class Derived < Base
   end

   class Derived2 < Base
     a 42.0
   end

   p Base.a
   p Derived.a
   p Derived2.a

   harp:~ > ruby a.rb
   42
   42.0

the inheritence is smart and allows overriding.

regards.

-a

···

On Wed, 12 Apr 2006, Andrew Thompson wrote:

Stephen Bannasch wrote:

I'd like to be able to create a class variable that will apply to all
objects made from that class and ALSO create a derived class with a
different class variable that is used in objects created from the
derived class WITHOUT affecting the class variable defined in the
original class.

Try a class instance variable vs a class variable:

class C
   @somevar = 'x'
   class << C
       def somevar
           @somevar
       end

       def somevar=(var)
           @somevar=var
       end
   end
end

Its not as easily accessible as a class variable (only accessible from
class methods) and you'd have to initialize it to something in derived
classes (otherwise it's nil) but its non-inherited. Not totally what you
want, but maybe it'll help.

Andrew

--
be kind whenever possible... it is always possible.
- h.h. the 14th dali lama