# Class methods like attr:

**URL:** <https://www.ruby-forum.com/t/class-methods-like-attr/52971>\
**Category:** Ruby\
**Created:** [January 21, 2006, 11:31pm UTC](https://www.ruby-forum.com/t/class-methods-like-attr/52971 "2006-01-21T23:31:09Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![gioele](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/8491ac/32.png) [@gioele](https://www.ruby-forum.com/u/gioele)\
**Post date:** [January 21, 2006, 11:31pm UTC](https://www.ruby-forum.com/t/class-methods-like-attr/52971/1 "2006-01-21T23:31:09Z")

</div>

How can I create methods like “attr:” that can create methods and  
instance  
variables?

I’d like to do this

class B \< A  
my\_property :k, “K”  
def test  
p @k # should print “K”  
p @@my\_properties # should print [‘k’]  
end  
end

I tried with this (non-) solution

class A  
def A.my\_property(sym, val)  
self.instance\_eval {  
@@my\_properties ||= Array.new()  
@@my\_properties \<\< sym.to\_s  
eval “@#{sym.id2name} = “#{val}””  
# p @k1 # \<\< this shows “K1.B” or “K1.C” as expected  
}  
end  
end

but these tests showed me that I was wrong

class A  
def test  
p @@my\_properties  
end  
end

class B \< A  
my\_property :k1, “K1.B” # k1 is a string fixed to “K1”  
my\_property :k2, “K2.B”  
def test  
super # should be [‘k1’, ‘k2’]  
p @k1 # should be “K1”  
end  
end

class C \< A  
my\_property :k1, “K1.C”  
def test  
super # should be [‘k1’]  
p @k1 # should be “K1.C”  
end  
end

A.new.test (should print nil or a warning) =\> [“k1”, “k2”, “k1”]

B.new.test (should print [‘k1’, ‘k2’] ‘K1.B’) =\> [“k1”, “k2”, “k1”]  
./at.rb:28: warning: instance variable @k1 not initialized  
nil

A.new.test (should print nil or a warning) =\> [“k1”, “k2”, “k1”]

C.new.test (should print [‘k1’] ‘K1.C’) =\> [“k1”, “k2”, “k1”]  
./at.rb:36: warning: instance variable @k1 not initialized  
nil

Any suggestion or idea?

---

<div class="post-metadata">

**Author:** ![gioele](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/8491ac/32.png) [@gioele](https://www.ruby-forum.com/u/gioele)\
**Post date:** [January 23, 2006, 4:25pm UTC](https://www.ruby-forum.com/t/class-methods-like-attr/52971/2 "2006-01-23T16:25:40Z")

</div>

Check this tutorial/game/artwork out:  
[http://poignantguide.net/dwemthy/](http://poignantguide.net/dwemthy/)

By the end, you will definitely know how to create methods that behave  
like attr\_accessor.

---

<div class="post-metadata">

**Author:** ![gioele](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/8491ac/32.png) [@gioele](https://www.ruby-forum.com/u/gioele)\
**Post date:** [January 24, 2006, 4:48pm UTC](https://www.ruby-forum.com/t/class-methods-like-attr/52971/3 "2006-01-24T16:48:34Z")

</div>

Here’s a quick hack. There are probably better ways.

def self.var\_with\_default(variable, default)  
@@current\_default = default  
class\_eval \<\<-END\_BLOCK  
@@default\_#{variable.to\_s} = @@current\_default  
attr\_writer #{variable.to\_s}  
def #{variable.to\_s}  
@#{variable.to\_s} || @@default\_#{variable.to\_s}  
end  
END\_BLOCK  
end

Include that in the class it will be used in (or an ancestor). This  
method is not thread safe.

---

<div class="post-metadata">

**Author:** ![gioele](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/8491ac/32.png) [@gioele](https://www.ruby-forum.com/u/gioele)\
**Post date:** [January 24, 2006, 5:37pm UTC](https://www.ruby-forum.com/t/class-methods-like-attr/52971/4 "2006-01-24T17:37:28Z")

</div>

Gioele B. wrote:

> ```
> end
> # p @k1 # << this shows "K1.B" or "K1.C" as expected
> 
> ```
> 
> end  
> class C \< A  
> /at.rb:28: warning: instance variable @k1 not initialized  
> nil
> 
> A.new.test (should print nil or a warning) =\> [“k1”, “k2”, “k1”]
> 
> C.new.test (should print [‘k1’] ‘K1.C’) =\> [“k1”, “k2”, “k1”]  
> /at.rb:36: warning: instance variable @k1 not initialized  
> nil
> 
> Any suggestion or idea?

One way is to define them as instance methods of class Module.

09:36:59 [~]: irb  
irb(main):001:0\> class Module  
irb(main):002:1\> def foo(sym)  
irb(main):003:2\> define\_method(sym) {|\*a| p a}  
irb(main):004:2\> end  
irb(main):005:1\> end  
=\> nil  
irb(main):006:0\> class Foo  
irb(main):007:1\> foo :bar  
irb(main):008:1\> end  
=\> #Proc:0x04aa36d0@:3(irb)  
irb(main):009:0\> Foo.new.bar 1,2,3  
[1, 2, 3]  
=\> nil

Then you can use them in the complete class hierarchy. If you want only  
part of the class hiearchy of classes to be able to use them, you should  
define them as instance methods of the starting class’s singleton class:

09:38:02 [~]: irb  
irb(main):001:0\> class Foo  
irb(main):002:1\> class \<\< self  
irb(main):003:2\> def foo(sym)  
irb(main):004:3\> define\_method(sym) {|\*a| p a}  
irb(main):005:3\> end  
irb(main):006:2\> end  
irb(main):007:1\> end  
=\> nil  
irb(main):008:0\> class Bar \< Foo  
irb(main):009:1\> foo :bar  
irb(main):010:1\> end  
=\> #Proc:0x04aa6bc8@:4(irb)  
irb(main):011:0\> Bar.new.bar  
[]  
=\> nil  
irb(main):012:0\> Bar.new.bar 1,2,3  
[1, 2, 3]  
=\> nil

Kind regards

```
robert
```
