Optional return values


#1

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


#2

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


#3

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


#4

2007/7/18, Andreas S. 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