Last active
June 9, 2016 13:18
-
-
Save wojtha/76a392a14a617294f293ad29530bf69e to your computer and use it in GitHub Desktop.
FailFast module proof of concept. Inspired by Hanami::Interactor
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| module FailFast | |
| class Success | |
| attr_reader :data, :error | |
| def initialize(data) | |
| @data = data | |
| end | |
| def success? | |
| true | |
| end | |
| def failure? | |
| false | |
| end | |
| end | |
| class Failure | |
| attr_reader :data, :error | |
| def initialize(error) | |
| @error = error | |
| end | |
| def success? | |
| false | |
| end | |
| def failure? | |
| true | |
| end | |
| end | |
| module Helpers | |
| def error(message) | |
| Failure.new(message) | |
| end | |
| def error!(message) | |
| throw :fail, error(message) | |
| end | |
| def fail!(result = false) | |
| throw :fail, result | |
| end | |
| def success(data) | |
| Success.new(data) | |
| end | |
| end | |
| def self.wrap(*method_names) | |
| Module.new do | |
| define_singleton_method :included do |base| | |
| proxy = Module.new do | |
| method_names.each do |m| | |
| define_method(m) do |*args| | |
| catch(:fail) do | |
| super(*args) | |
| end | |
| end | |
| end | |
| end | |
| base.include Helpers | |
| base.prepend proxy | |
| end | |
| end | |
| end | |
| def self.key_wrap(*method_names) | |
| Module.new do | |
| define_singleton_method :included do |base| | |
| proxy = Module.new do | |
| method_names.each do |m| | |
| define_method(m) do |*args, **kwargs| | |
| catch(:fail) do | |
| super(*args, **kwargs) | |
| end | |
| end | |
| end | |
| end | |
| base.include Helpers | |
| base.prepend proxy | |
| end | |
| end | |
| end | |
| def self.auto_wrap(*method_names) | |
| Module.new do | |
| define_singleton_method :included do |base| | |
| proxy = Module.new do | |
| method_names.each do |m| | |
| # We need to detect if method supports keyword arguments to provide | |
| # right parameters order when calling super() which doesn't support | |
| # implicit parameters passing in define_method. | |
| if base.instance_method(m).parameters.any? { |a| a[0] == :key } | |
| define_method(m) do |*args, **kwargs| | |
| catch(:fail) do | |
| super(*args, **kwargs) | |
| end | |
| end | |
| else | |
| define_method(m) do |*args| | |
| catch(:fail) do | |
| super(*args) | |
| end | |
| end | |
| end | |
| end | |
| end | |
| base.include Helpers | |
| base.prepend proxy | |
| end | |
| end | |
| end | |
| end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| require_relative 'fail_fast' | |
| class SomeOperation | |
| def call(error_level = 0) | |
| error! "Fatal error!" if error_level > 1 | |
| if error_level > 0 | |
| error "Warning!" | |
| else | |
| success "hello!" | |
| end | |
| end | |
| def keywords(error_level: 0) | |
| error! "Fatal error!" if error_level > 1 | |
| if error_level > 0 | |
| error "Warning!" | |
| else | |
| success "hello!" | |
| end | |
| end | |
| def plain(error_level = 0) | |
| if error_level > 1 | |
| fail! | |
| elsif error_level > 0 | |
| false | |
| else | |
| true | |
| end | |
| end | |
| # We need to include mdule after methods are loaded so we can introspect them | |
| include FailFast.auto_wrap :call, :keywords, :plain | |
| end | |
| service = SomeOperation.new | |
| puts "(0) =================================" | |
| result = service.call(0) | |
| puts result # => | |
| puts result.success? # => true | |
| puts result.error.inspect # => nil | |
| puts result.data.inspect # => "hello!"" | |
| puts "(1) =================================" | |
| result = service.call(1) | |
| puts result # => | |
| puts result.success? # => false | |
| puts result.error.inspect # => "Warning!" | |
| puts result.data.inspect # => nil | |
| puts "(2) =================================" | |
| result = service.call(2) | |
| puts result # => | |
| puts result.success? # => false | |
| puts result.error.inspect # => "Fatal error!" | |
| puts result.data.inspect # => nil | |
| puts "(3) =================================" | |
| result = service.keywords(error_level: 0) | |
| puts result # => | |
| puts result.success? # => true | |
| puts result.error.inspect # => nil | |
| puts result.data.inspect # => "hello!"" | |
| puts "(4) =================================" | |
| result = service.plain(0) | |
| puts result # => true | |
| puts "(6) =================================" | |
| result = service.plain(1) | |
| puts result # => false | |
| puts "(7) =================================" | |
| result = service.plain(2) | |
| puts result # => false |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment