require "test/unit" | |
class CountryMatcherTest < Test::Unit::TestCase | |
def test_valid_case | |
result = CountryMatcher.call("DE") do |match| | |
match.us { "US" } | |
match.de { "DE" } | |
match.gb { "GB" } | |
end | |
assert_equal result, "DE" | |
end | |
def test_valid_case_with_nil_result | |
result = CountryMatcher.call("DE") do |match| | |
match.us { "US" } | |
match.de {} | |
match.gb { "GB" } | |
end | |
assert_equal result, nil | |
end | |
def test_multiple_definitions | |
result = proc do | |
CountryMatcher.call("DE") do |match| | |
match.us { "US" } | |
match.de { "DE" } | |
match.de { "DE" } | |
match.gb { "GB" } | |
end | |
end | |
assert_raise(CountryMatcher::MultipleDefinitionError) { result.call } | |
end | |
def test_missing_definition | |
result = proc do | |
CountryMatcher.call("DE") do |match| | |
match.de { "DE" } | |
match.gb { "GB" } | |
end | |
end | |
assert_raise(CountryMatcher::MissingDefinitionError) { result.call } | |
end | |
def test_unknown_country | |
result = proc do | |
CountryMatcher.call("XX") do |match| | |
match.de { "DE" } | |
match.us { "US" } | |
match.gb { "GB" } | |
end | |
end | |
assert_raise(CountryMatcher::UnknownValueError) { result.call } | |
end | |
def test_unknown_case | |
result = proc do | |
CountryMatcher.call("DE") do |match| | |
match.xx { "XX" } | |
match.de { "DE" } | |
match.us { "US" } | |
match.gb { "GB" } | |
end | |
end | |
assert_raise(NoMethodError) { result.call } | |
end | |
end | |
class CountryMatcher | |
COUNTRIES = ["DE", "GB", "US"] | |
class MultipleDefinitionError < StandardError; end | |
class MissingDefinitionError < StandardError; end | |
class UnknownValueError < StandardError; end | |
class Match | |
def initialize(country) | |
@country = country | |
@calls = [] | |
end | |
COUNTRIES.each do |country| | |
define_method country.downcase do |&block| | |
if @calls.include?(country) | |
raise MultipleDefinitionError, country.inspect | |
end | |
@calls << country | |
@result = block.call if @country == country | |
end | |
end | |
def verify_and_return | |
difference.then do |missing| | |
if missing.any? | |
raise MissingDefinitionError, missing.inspect | |
end | |
end | |
if !COUNTRIES.include?(@country) | |
raise UnknownValueError, @country.inspect | |
end | |
@result | |
end | |
private | |
def difference | |
COUNTRIES.difference(@calls) + | |
@calls.difference(COUNTRIES) | |
end | |
end | |
def self.call(*args, **kwargs, &block) | |
new(*args, **kwargs).call(&block) | |
end | |
def initialize(value) | |
@value = value | |
end | |
def call | |
Match.new(@value).then do |match| | |
yield match | |
match.verify_and_return | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment