# Writing proper getter in a Ruby way

**URL:** <https://www.ruby-forum.com/t/writing-proper-getter-in-a-ruby-way/182164>\
**Category:** Ruby\
**Created:** [January 23, 2010, 6:36pm UTC](https://www.ruby-forum.com/t/writing-proper-getter-in-a-ruby-way/182164 "2010-01-23T18:36:45Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![benoitdinocourt](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/87869e/32.png) [@benoitdinocourt](https://www.ruby-forum.com/u/benoitdinocourt)\
**Post date:** [January 23, 2010, 6:36pm UTC](https://www.ruby-forum.com/t/writing-proper-getter-in-a-ruby-way/182164/1 "2010-01-23T18:36:45Z")

</div>

Hi Rubyists !

While writing a ‘getter’(it actually does more than just getting a  
@var’s value) method, I was wondering what was the most ruby-way to  
write it.

The ‘issue’ is  
if the @var is not initialized in constructor, and you access it  
directly like “@var”,  
Ruby gives you a warning(only if you enable them of course) :  
“warning: instance variable @value not initialized”

While “@var” returns nil as expected, it still show this warning.  
Well, I know you would probably not care too much about warnings(do  
you?), but how would you deal to make it disappear?

If you use attr\_\* methods, you’ll never see this warning, because it’s  
“cheating” (For what I understood of the C code, it checks if  
defined).

In fact, a ruby equivalent(for the user) of  
attr\_reader :var  
is  
def var  
instance\_variable\_defined?(:@var) ? @var : nil  
end  
and not just “@var” (because of the warning).

I think you will agree with me, using #instance\_variable\_defined? is  
not very nice.

Now I begin to describe the real code, because abstract examples would  
be hard.  
Here it is:

class Variable  
attr\_accessor :name, :proc  
attr\_writer :value

# Create a new Variable, with optional name, value and proc

def initialize(\*args, &proc)  
args.each do |arg|  
case arg  
when Numeric then @value = arg  
when String, Symbol then @name = arg.to\_s  
else raise ArgumentError, “…”  
end  
end  
@proc = proc  
end

def value  
@value or @proc && @proc.call.value  
end

def to\_s  
name || ‘unnamed\_variable’  
end  
end

So the constructor have optional \*args, and so we are not sure if a  
String or Symbol will be given for the name, neither if the value will  
be provided.

For #to\_s, I used the accessor(getter) of @name (“name”), that avoid  
me the warning(instead of @name || …)

But for value, it’s a bit complicated. Because we want to return or  
the value if given, or the result of the proc.  
I can’t use the accessor of value, because we are in a method with the  
same name …

There are then many possibles:

1. Initialize @value in #initialize : “@value = nil” or “@value =  
unnamed\_variable” (but it looks so old school)
2. Verify if @value is defined with #instance\_variable\_defined? :  
instance\_variable\_defined?(:@value) ? @value : @proc &&  
@proc.call.value (but it’s awful to read, btw #defined? still show the  
warning)
3. We don’t care about warnings !
4. bad names involve this conflict, we should rename @value (we can’t  
change the name of the method), and then use his accessor. The main  
problem is we’ll have then something like var.val = 2, which is less  
easy to understand than var.value = 2.
5. Another idea ? 😃

Excuse me if I’m writing very much for a very small problem, but I  
thank you already if you take time to read and/or reply 😉

Regards,  
B.D.

---

<div class="post-metadata">

**Author:** ![benoitdinocourt](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/87869e/32.png) [@benoitdinocourt](https://www.ruby-forum.com/u/benoitdinocourt)\
**Post date:** [January 24, 2010, 3:12pm UTC](https://www.ruby-forum.com/t/writing-proper-getter-in-a-ruby-way/182164/2 "2010-01-24T15:12:07Z")

</div>

2010/1/24 Marnen Laibow-Koser [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> def initialize(options, &proc)
> 
> > def to\_s  
> > name || ‘unnamed\_variable’  
> > end  
> > end
> 
> …and these can stay the same.

Thank you for your answer. I know that class checking is not so OO.  
The old behavior was like you propose: using a Hash. and then we were  
using  
@name, @value = options.values\_at(:name, :value) # values\_at is really  
nice here 🙂

That’s a very cool approach except it’s really longer and I think it’s  
significant in this context.  
We are writing a math library, this class represent a mathematical  
variable, so here we have:

x = var :x, 3 # with my way  
x = var name: :x, value: 3 # with hash, in 1.9  
x = var :name =\> :x, :value =\> 3 # with hash, in 1.8 (not relevant)  
To specify the name is already redundant with the real var name. It’s  
possible via caller to get it, with parsing, but that’s not a very  
good way neither. (Would you support that?)

So much checking in a case statement for classes looks bad, but it was  
intended to raise an ArgumentError if we still used the old behavior.

So, could I have your opinion, if we forget about Hash because it  
looks too long here ?  
Thank you for your answer again.

---

<div class="post-metadata">

**Author:** ![benoitdinocourt](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/87869e/32.png) [@benoitdinocourt](https://www.ruby-forum.com/u/benoitdinocourt)\
**Post date:** [January 24, 2010, 4:04am UTC](https://www.ruby-forum.com/t/writing-proper-getter-in-a-ruby-way/182164/3 "2010-01-24T04:04:05Z")

</div>

Benoit D. wrote:  
[…]

> Now I begin to describe the real code, because abstract examples would  
> be hard.  
> Here it is:
> 
> class Variable  
> attr\_accessor :name, :proc  
> attr\_writer :value
> 
> # Create a new Variable, with optional name, value and proc
> 
> def initialize(\*args, &proc)  
> args.each do |arg|  
> case arg  
> when Numeric then @value = arg  
> when String, Symbol then @name = arg.to\_s  
> else raise ArgumentError, “…”  
> end  
> end  
> @proc = proc  
> end

This seems a strange use case, but in any event, ou should not be doing  
this much class checking. I suggest a different approach entirely: pass  
a hash to the constructor rather like many Rails functions do.

So:

class Variable  
attr.accessor :name, :proc  
attr.writer :value

def initialize(options, &proc)  
@name = options[:name] ? options[:name].to\_s : nil  
@value = options[:value]  
@proc = proc  
end

> def value  
> @value or @proc && @proc.call.value  
> end
> 
> def to\_s  
> name || ‘unnamed\_variable’  
> end  
> end

…and these can stay the same.

## Best,

Marnen Laibow-Koser  
[http://www.marnen.org](http://www.marnen.org)  
removed\_email\_address@domain.invalid

---

<div class="post-metadata">

**Author:** ![benoitdinocourt](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/87869e/32.png) [@benoitdinocourt](https://www.ruby-forum.com/u/benoitdinocourt)\
**Post date:** [January 24, 2010, 3:36pm UTC](https://www.ruby-forum.com/t/writing-proper-getter-in-a-ruby-way/182164/4 "2010-01-24T15:36:44Z")

</div>

I assume the usual thing is to assign @value = nil in initialize() and  
call it a day.

But I think you are asking a higher-level question: How do we abstract  
away this detail?

The attr\_\* methods define methods which create instance variables upon  
first being called. But what if we want those instance variables to be  
initialized beforehand?

We would need to override the attr\_\* methods. But those methods belong  
to the class object–how are they going to initialize variables in the  
instances? By inserting code into the initialize() ancestor chain.

module InitializeAttr  
[:attr\_reader, :attr\_writer, :attr\_accessor].each do |method|  
define\_method method do |\*syms|  
super(\*syms).tap do  
mod = Module.new do  
define\_method :initialize do |\*args, &block|  
super(\*args, &block).tap do  
syms.each do |sym|  
instance\_variable\_set("@#{sym}", nil)  
end  
end  
end  
end  
include mod  
end  
end  
end  
end

class Control  
attr\_writer :a, :b  
def bar  
@a.to\_i + 5  
end  
end

control = Control.new  
p control.instance\_variables  
#=\> []  
p control.bar  
#=\> warning: instance variable @a not initialized  
#=\> 5

class Experiment  
extend InitializeAttr  
attr\_writer :a, :b  
def bar  
@a.to\_i + 5  
end  
end

exp = Experiment.new  
p exp.instance\_variables  
#=\> [:@a, :@b]  
p exp.bar  
#=\> 5

# yay no warnings

Therein lies either an abstraction technique or an overkill technique.

A few things about define\_method blocks,

- The &block argument is unsupported in Ruby 1.8.6. Sell your soul to  
eval() for a workaround.

- Implicit super arguments are broken in 1.8.7. It passes the regular  
arguments but forgets about the &block argument.

- In Ruby 1.9 super _must_ take explicit arguments. Don’t know why.

---

<div class="post-metadata">

**Author:** ![benoitdinocourt](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/87869e/32.png) [@benoitdinocourt](https://www.ruby-forum.com/u/benoitdinocourt)\
**Post date:** [January 24, 2010, 5:14pm UTC](https://www.ruby-forum.com/t/writing-proper-getter-in-a-ruby-way/182164/5 "2010-01-24T17:14:55Z")

</div>

Benoit D. wrote:

> 2010/1/24 Marnen Laibow-Koser [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):
> 
> > ï¿½def initialize(options, &proc)
> > 
> > > ï¿½ def to\_s  
> > > ï¿½ ï¿½ name || ‘unnamed\_variable’  
> > > ï¿½ end  
> > > end
> > 
> > …and these can stay the same.
> 
> Thank you for your answer. I know that class checking is not so OO.

It’s very OO. It’s just not very Rubyish.

> The old behavior was like you propose: using a Hash. and then we were  
> using  
> @name, @value = options.values\_at(:name, :value) # values\_at is really  
> nice here 🙂
> 
> That’s a very cool approach except it’s really longer and I think it’s  
> significant in this context.  
> We are writing a math library, this class represent a mathematical  
> variable,

Why do you need a separate class for this, instead of using Ruby’s  
variable mechanism?

> so here we have:
> 
> x = var :x, 3 # with my way  
> x = var name: :x, value: 3 # with hash, in 1.9  
> x = var :name =\> :x, :value =\> 3 # with hash, in 1.8 (not relevant)  
> To specify the name is already redundant with the real var name. It’s  
> possible via caller to get it, with parsing, but that’s not a very  
> good way neither. (Would you support that?)

No, that seems bad. I think you have three good choices for the  
constructor, then:

- Define the arguments positionally so that it’s always new(name, value)
- Pass a short hash: new(:x =\> 3)
- Use method\_missing: x = Variable.x(3)

> So much checking in a case statement for classes looks bad, but it was  
> intended to raise an ArgumentError if we still used the old behavior.

Then just check for a Hash!

Or better yet, support both syntaxes.

> So, could I have your opinion, if we forget about Hash because it  
> looks too long here ?

I don’t think that’s a great reason to drop it, but see above for other  
ideas.

> Thank you for your answer again.

## Best,

Marnen Laibow-Koser  
[http://www.marnen.org](http://www.marnen.org)  
removed\_email\_address@domain.invalid

---

<div class="post-metadata">

**Author:** ![benoitdinocourt](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/87869e/32.png) [@benoitdinocourt](https://www.ruby-forum.com/u/benoitdinocourt)\
**Post date:** [January 24, 2010, 6:40pm UTC](https://www.ruby-forum.com/t/writing-proper-getter-in-a-ruby-way/182164/6 "2010-01-24T18:40:43Z")

</div>

> I don’t have that:

When I said “A few things about define\_method blocks,” I meant this,

class P  
define\_method :m do |\*args, &b|  
[args, b]  
end  
end

class C \< P  
define\_method :m do |\*args, &b|  
p [args, b]  
p super  
end  
end

C.new.m(:a, :b) { |e| e }

Ruby 1.9:  
#=\> in `block in class:C’: implicit argument passing of super from  
method defined by define\_method() is not supported. Specify all  
arguments explicitly. (RuntimeError)

Ruby 1.8.7:  
#=\> [[:a, :b], #Proc:0x000270b0@test/iacc.rb:15]  
#=\> [[:a, :b], nil]

> So another way, probably less ‘overkill’ you made me think is:
> 
> class Test  
> attr\_reader :var  
> def initialize(\*args)  
> if args.length \> 0  
> @var = :value  
> end  
> end
> 
> alias :get\_var :var  
> def var  
> get\_var || 3  
> end  
> end
> 
> p Test.new.var #=\> 3  
> p Test.new(:arg1, :arg2).var #=\> :value

I dunno, it looks convoluted. Might as well go back to “old school”  
style, or if it becomes redundant you can use the previously mentioned  
technique to abstract like this,

initialized\_attr\_reader :var, 3

Going further, you can change the ‘3’ into a block evaluated by newly  
created instances.

Or maybe Struct is all you need for initializing variables,

Struct.new(:a, :b).new(2, 3)  
#=\> #\<struct #Class:0x90bdc a=2, b=3\>  
Struct.new(:a, :b).new  
#=\> #\<struct #Class:0x85070 a=nil, b=nil\>

---

<div class="post-metadata">

**Author:** ![benoitdinocourt](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/87869e/32.png) [@benoitdinocourt](https://www.ruby-forum.com/u/benoitdinocourt)\
**Post date:** [January 24, 2010, 4:51pm UTC](https://www.ruby-forum.com/t/writing-proper-getter-in-a-ruby-way/182164/7 "2010-01-24T16:51:37Z")

</div>

> I assume the usual thing is to assign @value = nil in initialize() and  
> call it a day.  
> That’s the first option, it just looks not cool at all, but it’s very  
> simple  
> an explicit, sure.

> ```
> end
> 
> ```
> 
> def bar
> 
> #=\> [:@a, :@b]  
> p exp.bar  
> #=\> 5
> 
> # yay no warnings
> 
> Therein lies either an abstraction technique or an overkill technique.  
> Cool way to do that 🙂 but overkill also…  
> It’s very interesting anyway how we can change that.

> A few things about define\_method blocks,
> 
> - The &block argument is unsupported in Ruby 1.8.6. Sell your soul to  
> eval() for a workaround.
> 
> - Implicit super arguments are broken in 1.8.7. It passes the regular  
> arguments but forgets about the &block argument.
> 
> - In Ruby 1.9 super _must_ take explicit arguments. Don’t know why.

I don’t have that:  
($ ruby -v #=\> ruby 1.9.2dev (2010-01-14 trunk 26319)  
[x86\_64-darwin10.2.0])  
class P  
def m(\*args, &b)  
[args, b]  
end  
end

class C \< P  
def m(\*args, &b)  
p [args, b]  
super.tap { |sup| p sup }  
end  
end

C.new.m(:a, :b) { |e| e }  
#=\> [[:a, :b], #Proc:...]  
#=\> [[:a, :b], #Proc:...]  
#=\> [:a, :b]

So another way, probably less ‘overkill’ you made me think is:

class Test  
attr\_reader :var  
def initialize(\*args)  
if args.length \> 0  
@var = :value  
end  
end

alias :get\_var :var  
def var  
get\_var || 3  
end  
end

p Test.new.var #=\> 3  
p Test.new(:arg1, :arg2).var #=\> :value

Just aliasing the old accessor, too easy 🙂 (and short, no line lost if  
we  
compare to initialization, and we suppose to have already other attr\_\*)  
I just forgot a moment name conflicts about methods don’t exist in Ruby,  
because you can so easily copy(alias) the old method.

Thanks for your answer 🙂

---

<div class="post-metadata">

**Author:** ![benoitdinocourt](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/87869e/32.png) [@benoitdinocourt](https://www.ruby-forum.com/u/benoitdinocourt)\
**Post date:** [January 24, 2010, 7:50pm UTC](https://www.ruby-forum.com/t/writing-proper-getter-in-a-ruby-way/182164/8 "2010-01-24T19:50:30Z")

</div>

Wait, why couldn’t you just call accessors through ‘self’?

class Foo  
attr\_accessor :a, :b  
def bar  
self.a.to\_i + 5  
end  
end

p Foo.new.bar  
#=\> 5

# (no warnings)

---

<div class="post-metadata">

**Author:** ![benoitdinocourt](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/87869e/32.png) [@benoitdinocourt](https://www.ruby-forum.com/u/benoitdinocourt)\
**Post date:** [January 24, 2010, 8:03pm UTC](https://www.ruby-forum.com/t/writing-proper-getter-in-a-ruby-way/182164/9 "2010-01-24T20:03:01Z")

</div>

> p Foo.new.bar  
> #=\> 5
> 
> # (no warnings)

We are in #value, to get @value …  
class C  
attr\_reader :var  
def var  
self.var || 2  
end  
end

C.new.var #=\> SystemStackError: stack level too deep

Anyway, we have chosen sth like:  
args.unshift nil if Numeric === args.first  
(@name, @value), @proc = args, proc

And then not using the accessor of attr\_\* for reading.  
It’s just a quick escape sequence from initialization.

Thanks for all your answers,  
Regards,  
B.D.
