Quick syntax question


#1

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


#2

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

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

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


#3

On 4/10/06, Gregory S. removed_email_address@domain.invalid wrote:

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, but the third
will be accessing @bar, not @@bar. (Try it in IRB and you’ll see.)

-austin


#4

On Apr 10, 2006, at 11:24 AM, Austin Z. 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.)

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


#5

On 4/10/06, Austin Z. removed_email_address@domain.invalid wrote:

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]]]]]]]]]]]]]


#6

On 4/10/06, Mark V. removed_email_address@domain.invalid 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.

-austin


#7

On 4/10/06, Austin Z. removed_email_address@domain.invalid wrote:

end
end
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.


#8

Hi –

On Tue, 11 Apr 2006, Mark V. wrote:

end
end

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


David A. Black (removed_email_address@domain.invalid)
Ruby Power and Light, LLC (http://www.rubypowerandlight.com)

“Ruby for Rails” coming in PDF April 15, and in paper May 1!
http://www.manning.com/black


#9

On Tue, 11 Apr 2006, Mark V. wrote:

end
end

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.

regards.

-a


#10

Hi –

On Tue, 11 Apr 2006, removed_email_address@domain.invalid wrote:

def self.bar=(val)
@@bar = val
Am I correct in believing that they are equivalent? If not, how do they
def a_class_method() end
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


David A. Black (removed_email_address@domain.invalid)
Ruby Power and Light, LLC (http://www.rubypowerandlight.com)

“Ruby for Rails” coming in PDF April 15, and in paper May 1!
http://www.manning.com/black


#11

On 4/10/06, Austin Z. removed_email_address@domain.invalid wrote:

On 4/10/06, Mark V. removed_email_address@domain.invalid 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.

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”


#12

On 4/10/06, removed_email_address@domain.invalid removed_email_address@domain.invalid wrote:

def self.bar=(val)
@@bar = val
Am I correct in believing that they are equivalent? If not, how do they
def a_class_method() end

 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.

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.


#13

On Tue, 11 Apr 2006, Mark V. 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.

cheers.

-a


#14

Hi –

On Tue, 11 Apr 2006, removed_email_address@domain.invalid wrote:

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 (removed_email_address@domain.invalid)
Ruby Power and Light, LLC (http://www.rubypowerandlight.com)

“Ruby for Rails” coming in PDF April 15, and in paper May 1!
http://www.manning.com/black


#15

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


#16

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.


#17

Stephen B. 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


#18

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
2968188
123abc
789abc
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.


#19

On Wed, 12 Apr 2006, Andrew T. wrote:

class C
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

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
42.0

the inheritence is smart and allows overriding.

regards.

-a