rubyraiseerror

Ruby assign a variable or raise error if nil


In kotlin and C#, you can assign a variable, or else if the value is nil, you can throw an exception using the ?: and ?? operators.

For example, in C#:

var targetUrl = GetA() ?? throw new Exception("Missing A");
// alt
var targetUrl = GetA() ?? GetB() ?? throw new Exception("Missing A or B");

Is this possible in ruby? If so, how?

Basically, what I want to do is this

target_url = @maybe_a || @maybe_b || raise "either a or b must be assigned"

I'm aware I can do this

target_url = @maybe_a || @maybe_b
raise "either a or b must be assigned" unless target_url

but I'd like to do it in a single line if possible


Solution

  • Basically, what I want to do is this

    target_url = @maybe_a || @maybe_b || raise "either a or b must be assigned"
    

    You have to add parentheses to raise to make your code work:

    x = a || b || raise("either a or b must be assigned")
    

    It would be "more correct" to use the control-flow operator or instead of ||: (which makes the parentheses optional)

    x = a || b or raise "either a or b must be assigned"
    

    This is Perl's "do this or die" idiom which I think is clean and neat. It emphases the fact that raise doesn't provide a result for x – it's called solely for its side effect.

    However, some argue that or / and are confusing and shouldn't be used at all. (see rubystyle.guide/#no-and-or-or)

    A pattern heavily used by Rails is to have two methods, one without ! which doesn't provide error handling:

    def a_or_b
      @maybe_a || @maybe_b
    end
    

    and one with ! which does:

    def a_or_b!
      a_or_b || raise("either a or b must be assigned")
    end
    

    Then call it via:

    target_url = a_or_b!