# Optional return values

**URL:** <https://www.ruby-forum.com/t/optional-return-values/109722>\
**Category:** Ruby\
**Created:** [July 18, 2007, 11:21am UTC](https://www.ruby-forum.com/t/optional-return-values/109722 "2007-07-18T11:21:29Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![andreas](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/ee7513/32.png) [@andreas](https://www.ruby-forum.com/u/andreas)\
**Post date:** [July 18, 2007, 11:21am UTC](https://www.ruby-forum.com/t/optional-return-values/109722/1 "2007-07-18T11:21:29Z")

</div>

Hi,

I have a few methods that check permissions, e.g.

unless user.can\_view?(object)  
puts “go away”  
end

What I want do do now is add the possibility to give the caller more  
information why the user doesn’t have permission. I want to make it  
backwards compatible, so returning [false, NotInGroupError(:group =\>  
‘xyz’)] is not an option. The only thing I could think of is giving the  
function a String or Array that is modified in place:

def can\_view?(object, message=’’)  
if foo.bar  
message.replace(‘some error message’)  
false  
else  
true  
end  
end

That’s how one would have to do it in C or VHDL. It does seem kinda  
un-rubyish though. Is there some obvious way to do this better that I’m  
missing?

Thanks  
Andreas

---

<div class="post-metadata">

**Author:** ![andreas](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/ee7513/32.png) [@andreas](https://www.ruby-forum.com/u/andreas)\
**Post date:** [July 18, 2007, 11:32am UTC](https://www.ruby-forum.com/t/optional-return-values/109722/2 "2007-07-18T11:32:13Z")

</div>

Alle mercoledÃ¬ 18 luglio 2007, Andreas S. ha scritto:

> backwards compatible, so returning [false, NotInGroupError(:group =\>  
> end
> 
> That’s how one would have to do it in C or VHDL. It does seem kinda  
> un-rubyish though. Is there some obvious way to do this better that I’m  
> missing?
> 
> Thanks  
> Andreas

I’do this:

def can\_view?(object, more\_info = false)  
if foo.bar  
more\_info ? [false, ‘message’] : false  
else  
more\_info ? [true, nil] : true  
end  
end

If the user doesn’t specify the second argument, then the method works  
as the  
original version, otherwise it returns an array whose first argument is  
true  
or false and whose second argument is nil if the user has the  
perimission or  
the reason he doesn’t if he doesn’t (in the example above, I used a  
string,  
but it can be anything, of course). The only drawback I can see with  
this  
approach is that you can simply test the condition using

if can\_view?(obj, true)  
#…  
but you need

if can\_view?(obj,true)[0]  
#…

I hope this helps

Stefano

---

<div class="post-metadata">

**Author:** ![andreas](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/ee7513/32.png) [@andreas](https://www.ruby-forum.com/u/andreas)\
**Post date:** [July 18, 2007, 1:16pm UTC](https://www.ruby-forum.com/t/optional-return-values/109722/3 "2007-07-18T13:16:28Z")

</div>

Andreas S. wrote:

> backwards compatible, so returning [false, NotInGroupError(:group =\>  
> ‘xyz’)] is not an option.

Maybe turn it into a block?

user.cannot\_view?(object) do |msg|  
puts msg  
end

Daniel

---

<div class="post-metadata">

**Author:** ![andreas](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/ee7513/32.png) [@andreas](https://www.ruby-forum.com/u/andreas)\
**Post date:** [July 18, 2007, 1:36pm UTC](https://www.ruby-forum.com/t/optional-return-values/109722/4 "2007-07-18T13:36:38Z")

</div>

2007/7/18, Andreas S. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> backwards compatible, so returning [false, NotInGroupError(:group =\>  
> ‘xyz’)] is not an option. The only thing I could think of is giving the  
> function a String or Array that is modified in place:

I would not do that - that’s plain awful for a language that has  
multiple return values.

Some options I can think of that are better:

- create another method returning the reason
- use exceptions, i.e. do not check but simply do something and throw  
if the permission is not granted (typically methods dealing with the  
file system do it this way)
- create another method returning a boolean and a reason, but do not  
use a question mark as last character in the identifier
- invert the logic, i.e. def permission\_denied? which returns the  
reason if forbidden and nil if granted (though I find this a bit  
hackish)

I’d probably favor raising exceptions.

Kind regards

robert
