I will define value. But this value may be in value of key of hash. I will use rescue for define value is nil if this keys is not exist. for example
foo = bar[:a][:b][:c] rescue nil
But in practice tell me bad style because me using rescue in its modifier form. I will change logic to use check three condition.
foo = bar[:a][:b][:c] if bar.key?(:a) && bar[:a].key?(:b) && bar[:a][:b].key?(:c)
I really would like to know why should we avoid using rescue in its modifier form?
Why should we avoid using rescue in its modifier form in rails?
Firstly, because it hides all errors, including the ones you expect and the ones you don't, and a blanket rescue
doesn't make it clear to future readers of your code which errors were expected or unexpected. This might not be a problem now, with a simple foo[:a][:b][:c]
, but at any given point in time somebody might modify that statement to read foo[:a][:b][some_method]
and suddenly any errors that should bubble out of some_method
are also swallowed.
Secondly, there is usually a better less all-encompassing solution that is more explicitly designed to handle only the error you intend to ignore: A missing index or a nil
return value.
In your case, the alternative is not the massive if && && &&
you're suggesting. For a hash, you can use either dig
, which has all the benefits of rescue
without swallowing every type of exception that could be raised:
foo = bar.dig(:a, :b, :c)
Similarly, for chained method invocations, you can use try
(in Rails) or the safe navigation operator (in Ruby 2.3):
foo = bar.try(:a).try(:b).try(:c)
# or
foo = bar&.a&.b&.c
The longer form is more safe, I wouldn't use the short version in production unless there is no other way. Whether you use checks or an exeption to avoid or catch errors depends on the situation. Exeptions are costly in processor time, so do your benchmarks for time consuming methods, on the other hand doing a lot of checks and still not being sure is perhaps worse. If the readability of my code would be lost by doing a lot of checks and speed isn't a factor I use begin .. rescue or def .. rescue but in that case you are better to rescue a known exception like this
begin
# -
raise "another exception"
rescue SyntaxError
# -
rescue => exception
@errors += 1
log exception
log exception.backtrace
end
Which gives
another exception
C:/.../test.rb:3:in `<main>'
Always catch the kind of exception and put or better log it, I also use it to raise a variable @errors which is logged for all of my scripts and monitored by a separate tool.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With