{"id":415,"date":"2013-09-18T13:26:07","date_gmt":"2013-09-18T13:26:07","guid":{"rendered":"http:\/\/nicholshayes.co.uk\/blog\/?p=415"},"modified":"2015-01-09T08:59:05","modified_gmt":"2015-01-09T08:59:05","slug":"intercepting-ruby-exceptions","status":"publish","type":"post","link":"http:\/\/nicholshayes.co.uk\/blog\/?p=415","title":{"rendered":"Intercepting Ruby exceptions"},"content":{"rendered":"<p>The way some Ruby applications catch exceptions makes it more difficult to debug the underlying issue. That is because a common pattern for handling an exception is this:<\/p>\n<div class=\"codecolorer-container ruby default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"ruby codecolorer\"><span class=\"kw1\">begin<\/span><br \/>\n&nbsp; do_something_that_fails<br \/>\n<span class=\"kw1\">rescue<\/span> SomeError<br \/>\n&nbsp; <span class=\"kw3\">raise<\/span> MyAppError.<span class=\"me1\">new<\/span> <span class=\"st0\">&quot;Something went wrong&quot;<\/span><br \/>\n<span class=\"kw1\">end<\/span><\/div><\/div>\n<p>So where is the problem? The problem is that by capturing the error in this way, the originals exception information is lost. That is, the original exception usually contains a message and back-trace that make debugging the error easier. With the pattern above, the output is only the MyAppError message, and the back trace to this code.<\/p>\n<p>Recently, this issue has led to me not trapping errors as much as I used to, because letting the underlying exception bubble up through my apps has often resulted in more meaningful and useful errors. However, I&#8217;ve just found <a href=\"https:\/\/github.com\/skorks\/nesty\">nesty<\/a>, and I think it is the solution to this issue. That is, it allows exceptions to be caught, flagged and handled within an app, whilst preserving the original error message and back-trace.<\/p>\n<p>I&#8217;ve been playing with nesty and the result is three simple ruby programs that I believe demonstrate the value of the nesty approach to handling exceptions from underlying code. <\/p>\n<p>I&#8217;ve created three files that contain the code shown below. Each one has <em>File.new(&#8216;no_such_file&#8217;)<\/em> called on line 8 so that there is some consistency between the errors raised by each example. (Unfortunately the empty lines used to achieve this don&#8217;t display output in this blog &#8211; so please assume that  <em>File.new(&#8216;no_such_file&#8217;)<\/em> is always on line 8 )<\/p>\n<p><strong>Version one: No Error handling<\/strong><\/p>\n<div class=\"codecolorer-container ruby default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"ruby codecolorer\">&nbsp; <span class=\"kw4\">File<\/span>.<span class=\"me1\">new<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">'no_such_file'<\/span><span class=\"br0\">&#41;<\/span><\/div><\/div>\n<p>The error output when this run is:<\/p>\n<div class=\"codecolorer-container text default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"text codecolorer\">wrong_file.rb:8:in `initialize': No such file or directory - no_such_file (Errno::ENOENT)<br \/>\n&nbsp; &nbsp; from wrong_file.rb:8:in `new'<br \/>\n&nbsp; &nbsp; from wrong_file.rb:8:in `&lt;main&gt;'<\/div><\/div>\n<p>So a nice meaningful error that tells me what the underlying issue was. However, it would be nice if I could add some information about what I was trying to do when this error occurred. To do that I need to trap the error and handle it.<\/p>\n<p><strong>Version two: Trap the error and raise an app specific exception<\/strong><\/p>\n<div class=\"codecolorer-container ruby default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"ruby codecolorer\"><span class=\"kw1\">class<\/span> MyError <span class=\"sy0\">&lt;<\/span> <span class=\"kw4\">StandardError<\/span><br \/>\n<br \/>\n<span class=\"kw1\">end<\/span><br \/>\n<br \/>\n<span class=\"kw1\">begin<\/span><br \/>\n&nbsp; <span class=\"kw4\">File<\/span>.<span class=\"me1\">new<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">'no_such_file'<\/span><span class=\"br0\">&#41;<\/span><br \/>\n<span class=\"kw1\">rescue<\/span><br \/>\n&nbsp; <span class=\"kw3\">raise<\/span> MyError.<span class=\"me1\">new<\/span> <span class=\"st0\">&quot;Unable to access file&quot;<\/span><br \/>\n<span class=\"kw1\">end<\/span><\/div><\/div>\n<p>This outputs this error message:<\/p>\n<div class=\"codecolorer-container ruby default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"ruby codecolorer\">wrong_file_rescued.<span class=\"me1\">rb<\/span>:<span class=\"nu0\">10<\/span>:<span class=\"kw1\">in<\/span> <span class=\"st0\">`rescue in &lt;main&gt;': Unable to access file (MyError)<br \/>\n&nbsp; &nbsp; from wrong_file_rescued.rb:7:in `<\/span><span class=\"sy0\">&lt;<\/span>main<span class=\"sy0\">&gt;<\/span><span class=\"st0\">'<\/span><\/div><\/div>\n<p>This contains error information that is specific to my app, but a lot of information is lost. Even the line number where the error occurred is lost. Line 7 is the begin statement.<\/p>\n<p><strong>Version three: Add nesty<\/strong><\/p>\n<div class=\"codecolorer-container ruby default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"ruby codecolorer\"><span class=\"kw3\">require<\/span> <span class=\"st0\">'nesty'<\/span><br \/>\n<br \/>\n<span class=\"kw1\">class<\/span> MyError <span class=\"sy0\">&lt;<\/span> <span class=\"kw4\">StandardError<\/span><br \/>\n&nbsp; <span class=\"kw1\">include<\/span> <span class=\"re2\">Nesty::NestedError<\/span><br \/>\n<span class=\"kw1\">end<\/span><br \/>\n<br \/>\n<span class=\"kw1\">begin<\/span><br \/>\n&nbsp; <span class=\"kw4\">File<\/span>.<span class=\"me1\">new<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">'no_such_file'<\/span><span class=\"br0\">&#41;<\/span><br \/>\n<span class=\"kw1\">rescue<\/span><br \/>\n&nbsp; <span class=\"kw3\">raise<\/span> MyError.<span class=\"me1\">new<\/span> <span class=\"st0\">&quot;Unable to access file&quot;<\/span><br \/>\n<span class=\"kw1\">end<\/span><\/div><\/div>\n<p>And this outputs:<\/p>\n<div class=\"codecolorer-container text default\" style=\"overflow:auto;white-space:nowrap;\"><div class=\"text codecolorer\">wrong_file_nesty.rb:10:in `rescue in &lt;main&gt;': Unable to access file (MyError)<br \/>\n&nbsp; &nbsp; from wrong_file_nesty.rb:7:in `&lt;main&gt;'<br \/>\n&nbsp; &nbsp; from wrong_file_nesty.rb:8:in `initialize': No such file or directory - no_such_file (Errno::ENOENT)<br \/>\n&nbsp; &nbsp; from wrong_file_nesty.rb:8:in `new'<br \/>\n&nbsp; &nbsp; from wrong_file_nesty.rb:8:in `&lt;main&gt;'<\/div><\/div>\n<p>Now I have the best of both worlds: both my app specific error details and those of the underlying exception.<\/p>\n<p>I found nesty via the authors blog: <a href=\"http:\/\/www.skorks.com\/2013\/04\/ruby-why-u-no-have-nested-exceptions\/\">Skorks<\/a>,  and I&#8217;d thoroughly recommend you have a look at that (and the rest of that excellent blog).<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The way some Ruby applications catch exceptions makes it more difficult to debug the underlying issue. That is because a common pattern for handling an exception is this: begin &nbsp; do_something_that_fails rescue SomeError &nbsp; raise MyAppError.new &quot;Something went wrong&quot; end &hellip; <a href=\"http:\/\/nicholshayes.co.uk\/blog\/?p=415\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":3,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[3],"tags":[11],"_links":{"self":[{"href":"http:\/\/nicholshayes.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts\/415"}],"collection":[{"href":"http:\/\/nicholshayes.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/nicholshayes.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/nicholshayes.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"http:\/\/nicholshayes.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=415"}],"version-history":[{"count":16,"href":"http:\/\/nicholshayes.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts\/415\/revisions"}],"predecessor-version":[{"id":520,"href":"http:\/\/nicholshayes.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts\/415\/revisions\/520"}],"wp:attachment":[{"href":"http:\/\/nicholshayes.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=415"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/nicholshayes.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=415"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/nicholshayes.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=415"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}