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?
Is there anyway to return false, “reason”, or something of that sort?
What is the preferred, idiomatic way of doing this?
use a block to return info:
harp:~ > cat a.rb
class C
def initialize(x) @x = x end
def valid?()
if @x == 42
true
else
yield "x is not 42" rescue nil
false
end
end
end
c = C::new 43
unless c.valid?{|reason| warn "not valid : #{ reason }" }
# do something
end
c = C::new 42
c.valid?{|reason| warn "not valid : #{ reason }" }
harp:~ > ruby a.rb
not valid : x is not 42
or invert your logic so info can be added:
harp:~ > cat a.rb
class C
def initialize(x) @x = x end
def invalid?() @x == 42 ? false : “x is not 42” end
end
c = C::new 43
if((reason = c.invalid?))
puts reason
end
c = C::new 42
if((reason = c.invalid?))
puts reason
end
I like this solution the best. Unlike the solutions involving
exceptions or multiple return values, it still allows valid? to be used
as an ordinary boolean function when you don’t care about the reason why
something’s not valid, yet doesn’t have the race conditions involved in
the side-effect solutions.
That said, I think part of the reason there’s no agreed upon idiom for
this is because it would have been more idiomatic in Ruby to not even
have the valid? method. Instead an exception would have been thrown as
soon as the object became invalid, and the exception would have
contained the reason. Having your class have a valid? method seems like
how you’d design things in a language which doesn’t have exceptions.
That said, I think part of the reason there’s no agreed upon idiom for this
is because it would have been more idiomatic in Ruby to not even have the
valid? method. Instead an exception would have been thrown as soon as the
object became invalid, and the exception would have contained the reason.
Having your class have a valid? method seems like how you’d design things in
a language which doesn’t have exceptions.
still - some people prefer not to do control flow with exceptions. as
with
most things, both things can be good. i tend to use things like
def validate!
raise unless valid?
end
and use either/both where it makes sense.
regards.
-a
This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.