0
def run
  ...

rescue FooError
  ...

rescue
  ...

ensure
  ...
end

How to suppress the ensure block only for FooError?

B Seven
  • 44,484
  • 66
  • 240
  • 385

1 Answers1

5

What about this?

def run
  ...

rescue FooError
  rescued_foo_error = true
  ...

rescue
  ...

ensure
  unless rescued_foo_error
    ...
  end
end
spickermann
  • 100,941
  • 9
  • 101
  • 131
  • 1
    This seems to work fine (so long as the `begin` keyword is added), but I don't understand why `rescued_foo_error` doesn't raise a "no method or local variable" exception when `FooError` is not raised. That is, I thought you needed to initialize `rescued_foo_error` to `nil` or `false` at the beginning, but not so. Does Ruby create that local variable and initialize it to zero when parsing the `rescue` block (as it does when parsing some `if` statements)? – Cary Swoveland Oct 08 '19 at 00:46
  • Sounds like it works the same as an `if` statement. Otherwise undefined variables are defined and set to `nil`. I think it has to do with the parser: https://stackoverflow.com/questions/12614805/why-can-i-refer-to-a-variable-outside-of-an-if-unless-case-statement-that-never – B Seven Oct 08 '19 at 02:27
  • 3
    @CarySwoveland since the variable is declared inside the current closure (def..end) and prior to the reference in unless, the parser (reading from top to bottom) recognizes the "local-variable" assignment in the lexical scope but since the assignment never occurs it is `nil`. As you mentioned the same occurs for if statements as it appears ruby does not consider `if` or `begin..end` as true closures. However constant definition does not follow the same rules for example `begin; raise; rescue ArgumentError; Foo = StandardError; ensure; Foo; end;` will result in an uninitialized constant. – engineersmnky Oct 08 '19 at 18:38