# Idiomatic ruby

**URL:** <https://www.ruby-forum.com/t/idiomatic-ruby/66323>\
**Category:** Ruby\
**Created:** [February 13, 2006, 12:23am UTC](https://www.ruby-forum.com/t/idiomatic-ruby/66323 "2006-02-13T00:23:35Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [February 13, 2006, 12:23am UTC](https://www.ruby-forum.com/t/idiomatic-ruby/66323/1 "2006-02-13T00:23:35Z")

</div>

Very often I have a question method, which, in some cases, the caller  
would want to know why as well.

Examples:

def valid?  
end

def abort?  
end

Ruby does not allow subclassing true and false, so, if these methods  
return one of those, they can’t return any additional info. But  
sometimes the caller needs additional info, as in:

if !valid? logger.warn “Not valid: #{why not?}”

What is the best way to handle this? I could have those methods set  
@instance\_variables, but this seems a little hackish, and could  
introduce race conditions.

Is there anyway to return false, “reason”, or something of that sort?  
What is the preferred, idiomatic way of doing this?

---

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [February 13, 2006, 12:52am UTC](https://www.ruby-forum.com/t/idiomatic-ruby/66323/2 "2006-02-13T00:52:45Z")

</div>

DÅ?a Pondelok 13 FebruÃ¡r 2006 00:23 removed\_email\_address@domain.invalid napÃ­sal:

> Ruby does not allow subclassing true and false, so, if these methods  
> return one of those, they can’t return any additional info. But  
> sometimes the caller needs additional info, as in:

You can subclass TrueClass or FalseClass, it just wouldn’t do you much  
good.

> if !valid? logger.warn “Not valid: #{why not?}”
> 
> What is the best way to handle this? I could have those methods set  
> @instance\_variables, but this seems a little hackish, and could  
> introduce race conditions.

Have whatever method changes state in the context of the snippet you  
posted  
return a object describing the result of an operation, including both  
those  
predicates and the reason?

Besides, the #valid? and #abort? methods would still be subject to the  
same  
race conditions as any other place you’d store a reason info, I think.  
Personally, I smell some design weirdness, but can’t really blame it  
with  
this little context.

David V.

---

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [February 13, 2006, 1:19am UTC](https://www.ruby-forum.com/t/idiomatic-ruby/66323/3 "2006-02-13T01:19:30Z")

</div>

removed\_email\_address@domain.invalid wrote:

> Ruby does not allow subclassing true and false, so, if these methods  
> return one of those, they can’t return any additional info. But  
> sometimes the caller needs additional info, as in:
> 
> if !valid? logger.warn “Not valid: #{why not?}”

Use exceptions, which can contain readable messages

def my\_meth  
validate  
# … proceed  
rescue =\> err  
logger.warn “Not valid #{err}”  
end

# if you want a boolean-style method

def valid?  
validate && true # assuming validate returns some kind of true value  
rescue  
false  
end

alex

---

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [February 13, 2006, 5:04pm UTC](https://www.ruby-forum.com/t/idiomatic-ruby/66323/4 "2006-02-13T17:04:52Z")

</div>

> What is the best way to handle this? I could have those methods set  
> @instance\_variables, but this seems a little hackish, and could  
> introduce race conditions.

I’m not sure I’d agree that it is hackish to set @instance\_variables (or  
perhaps to use a setter instead) to capture learned info. A naming  
convention might help (maybe remove the "?’ and add “\_reason”)

class Foo  
attr\_accessor :valid\_reason  
def valid?  
…  
self.valid\_reason = “age is too young”  
false  
end  
end

---

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [February 13, 2006, 1:04am UTC](https://www.ruby-forum.com/t/idiomatic-ruby/66323/5 "2006-02-13T01:04:04Z")

</div>

How about returning multiple values?

def valid?  
[@is\_valid\_flag, @error\_message]  
end

---

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [February 13, 2006, 1:33am UTC](https://www.ruby-forum.com/t/idiomatic-ruby/66323/6 "2006-02-13T01:33:37Z")

</div>

DÅ?a Pondelok 13 FebruÃ¡r 2006 01:03 Phrogz napÃ­sal:

> How about returning multiple values?
> 
> def valid?  
> [@is\_valid\_flag, @error\_message]  
> end

Wouldn’t ever evaluate as false, which means all the predicates would  
have to  
be true on a failure, which might be a bit confusing - I prefer to code  
assertively if possible.

David V.

---

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [February 13, 2006, 5:23pm UTC](https://www.ruby-forum.com/t/idiomatic-ruby/66323/7 "2006-02-13T17:23:59Z")

</div>

Brian B. wrote:

> attr\_accessor :valid\_reason  
> def valid?  
> …  
> self.valid\_reason = “age is too young”  
> false  
> end  
> end

IMHO it’s bad practice to store this info in the instance. It really  
doesn’t belong there; you run into all sorts of problems (race  
conditions  
in concurrent apps, consistence - you need to clear this when the  
instance  
state changes…).

The best solution seems to be to use an exception.

class Foo  
attr\_accessor :name

def ensure\_valid  
self.name or raise “Empty name.”  
end  
end

begin  
f=Foo.new  
f.ensure\_valid  
f.do\_stuff()  
rescue RuntimeError =\> e  
$stderr.puts “Invalid because of: #{e.message}”  
end

Kind regards

```
robert
```
