def test
(err = _invalid_permission) && return err
#do something else
end
Combine two statements with return into one in Ruby
-
28-09-2022 - |
Question
Is there a way to make this function into one statement?
def test
err = _invalid_permission
return err if err # this statement
# do something else
end
I tried:
def test
return (err = _invalid_permission) if err
# do something else
end
but this is different, err
after if
is always nil
Or this one:
def test
return err if (err = _invalid_permission)
# do something else
end
but this one causes undefined local variable or method 'err'
.
explanation for what i trying to do is to shorten these kind of method:
def test
err = _invalid_permission
return err if err
err = _check_another_error
return err if err
err = _and_another_one
return err if err
# and lots more
# do something else when not error
return nil
end
the _invalid_permission
, _check_another_error
, and _and_another_one
would return non-empty string or array or hash containing the error message.
another story, after seeing answers below, i think it could combined into:
def test
err = _invalid_permission ||
_check_another_error ||
_and_another_one
# and lots more
return err if err
# do something else when not error
return nil
end
Solution
OTHER TIPS
Are you sure you've asked the right question? You've focused on one way to reduce the lines of code you have to write. Instead, you need to DRY out your code. Here's one way:
module Checks
def _invalid_permission() nil end
def _check_another_error() "oops!" end
def _and_another_one() nil end
end
class Doit
@@checks = Checks.instance_methods(false)
include Checks
def doit
@@checks.each { |m| rv = send(m); return rv if rv }
"test"
end
end
p Doit.new.doit # => "oops!"
If you change
def _check_another_error() "oops!" end
to
def _check_another_error() nil end
then
p Doit.new.doit # => "test"
This approach also allows you to add, remove or rename a check method without having to remember to change references to it elsewhere.
This works, but you would sacrifice clarity
def test
(err = _invalid_permission) ? (return err) : nil
#do something
end
def test
(err = _invalid_permission) or begin
# do something else
end
end
This doesn't go into combining statements, but if what you're trying to do is check a bunch of error conditions like you show, it can be done more readably with something like this:
def test
err ||= _invalid_permission
err ||= _check_another_error
err ||= _and_another_one
return err if err
#do a bunch of other stuff
end
Or, if you do this in a lot of places, it sounds like an exception might make sense. Something like:
class MyValidationError < Exception
attr_accessor :err
def initialize(err)
@err = err
end
end
def check(err_or_nil)
raise MyValidationError.new(err) if err_or_nil
end
def test
check _invalid_permission
check _check_another_error
check _and_another_one
#do a bunch of other stuff
rescue MyValidationError
$!.err
end
But I think the first is quite readable, personally.