├── lib └── rescue-with.rb ├── rescue-with.gemspec ├── .gitignore ├── LICENSE └── README.md /lib/rescue-with.rb: -------------------------------------------------------------------------------- 1 | def StandardError.with 2 | self === $! ? yield($!) : fail 3 | end 4 | -------------------------------------------------------------------------------- /rescue-with.gemspec: -------------------------------------------------------------------------------- 1 | Gem::Specification.new do |s| 2 | s.name = 'rescue-with' 3 | s.version = '1.0.1' 4 | s.summary = 'Inline rescue a specific exception type' 5 | s.description = 'Adds `... rescue ExceptionType.with { ... }`' 6 | s.author = 'Kaiting Chen' 7 | s.email = 'ktchen14@gmail.com' 8 | s.files = ['lib/rescue-with.rb'] 9 | s.homepage = 'https://github.com/ktchen14/rescue-with' 10 | s.license = 'Unlicense' 11 | end 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | *.rbc 3 | /.config 4 | /coverage/ 5 | /InstalledFiles 6 | /pkg/ 7 | /spec/reports/ 8 | /spec/examples.txt 9 | /test/tmp/ 10 | /test/version_tmp/ 11 | /tmp/ 12 | 13 | # Used by dotenv library to load environment variables. 14 | # .env 15 | 16 | ## Specific to RubyMotion: 17 | .dat* 18 | .repl_history 19 | build/ 20 | *.bridgesupport 21 | build-iPhoneOS/ 22 | build-iPhoneSimulator/ 23 | 24 | ## Specific to RubyMotion (use of CocoaPods): 25 | # 26 | # We recommend against adding the Pods directory to your .gitignore. However 27 | # you should judge for yourself, the pros and cons are mentioned at: 28 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 29 | # 30 | # vendor/Pods/ 31 | 32 | ## Documentation cache and generated files: 33 | /.yardoc/ 34 | /_yardoc/ 35 | /doc/ 36 | /rdoc/ 37 | 38 | ## Environment normalization: 39 | /.bundle/ 40 | /vendor/bundle 41 | /lib/bundler/man/ 42 | 43 | # for a library or gem, you might want to ignore these files since the code is 44 | # intended to run in multiple environments; otherwise, check them in: 45 | # Gemfile.lock 46 | # .ruby-version 47 | # .ruby-gemset 48 | 49 | # unless supporting rvm < 1.11.0 or doing something fancy, ignore this: 50 | .rvmrc 51 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or distribute this 4 | software, either in source code form or as a compiled binary, for any purpose, 5 | commercial or non-commercial, and by any means. 6 | 7 | In jurisdictions that recognize copyright laws, the author or authors of this 8 | software dedicate any and all copyright interest in the software to the public 9 | domain. We make this dedication for the benefit of the public at large and to 10 | the detriment of our heirs and successors. We intend this dedication to be an 11 | overt act of relinquishment in perpetuity of all present and future rights to 12 | this software under copyright law. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 16 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE 17 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 18 | CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 19 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | 21 | For more information, please refer to 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # rescue-with 2 | 3 | Inline rescue a specific exception type in Ruby. 4 | 5 | ## Background 6 | 7 | The modifier form of `rescue` in Ruby 8 | [can](https://github.com/bbatsov/ruby-style-guide#no-rescue-modifiers) 9 | [be](https://rubocop.readthedocs.io/en/latest/cops_style/#stylerescuemodifier) 10 | [dangerous](https://www.rubytapas.com/2012/11/12/episode-022-inline-rescue/) 11 | because it rescues from `StandardError` and can't be targeted toward a more 12 | specific exception. To rescue from a specific exception the full `begin ... 13 | rescue ... end` syntax must be used which can be needlessly verbose as evident 14 | from this [proposal](https://bugs.ruby-lang.org/issues/6739) from 2013. 15 | 16 | ## Installation 17 | 18 | ``` 19 | gem install rescue-with 20 | ``` 21 | 22 | ## Usage 23 | 24 | To use this gem required it with: 25 | 26 | ```ruby 27 | require 'rescue-with' 28 | ``` 29 | 30 | This gem adds the syntax: 31 | 32 | ```ruby 33 | ... rescue ExceptionType.with { ... } 34 | ``` 35 | 36 | To rescue from `ExceptionType` and return the result `{ ... }`. If you need the 37 | exception itself and don't want to use `$!` then do: 38 | 39 | ```ruby 40 | ... rescue ExceptionType.with { |e| ... } 41 | ``` 42 | 43 | ## Example 44 | 45 | Output an error message to `stderr` if a file can't be read: 46 | 47 | ```ruby 48 | data = File.read('none') rescue Errno::ENOENT.with { $stderr.puts('No data') } 49 | ``` 50 | 51 | ## Caveats 52 | 53 | Because the modifier form of `rescue` only rescues from `StandardError` this 54 | syntax only works if `StandardError` is an ancestor of `ExceptionType`. This 55 | shouldn't be a problem most of the time as `Exception`s that aren't a subclass 56 | of `StandardError` are rarely rescued. 57 | 58 | Note that `StandardError#with` only rescues a single type of exception. If you 59 | need to rescue multiple types of exceptions it's much better to use the `begin 60 | ... rescue ... end` syntax. 61 | 62 | ## License 63 | 64 | The gem is available as open source under the terms of [The 65 | Unlicense](http://unlicense.org/). 66 | --------------------------------------------------------------------------------