require "json" require "blood_contracts/core" module Types class JSON < BC::Refined def match context[:parsed] = ::JSON.parse(value) self rescue StandardError => error failure(error) end def mapped context[:parsed] end end class Tariff < BC::Refined def match context[:data] = value.slice("cost", "cur").compact context[:tariff_context] = 1 return if context[:data].size == 2 failure(:not_a_tariff) end def mapped context[:data] end end class Error < BC::Refined def match context[:data] = unpack_refined(value).slice("code", "message").compact context[:known_error_context] = 1 return if context[:data].size == 2 failure(:not_a_known_error) end def mapped context[:data] end end Response = BC::Pipe.new( BC::Anything, JSON, (Tariff | Error | Tariff), names: %i[raw parsed mapped] ) # The same is # Response = BC::Anything.and_then(JSON).and_then(Tariff | Error) do # class Response # self.names = [:raw, :parsed, :mapped] # end # # or # # Response = BC::Pipe.new(BC::Anything, JSON, Tariff | Error) do # self.names = [:raw, :parsed, :mapped] # end end def match_response(response) match = Types::Response.match(response) case match when Types::Tariff # работаем с тарифом puts "match.context # => #{match.context} \n\n" puts "render json: { tariff: #{match.unpack} }" when Types::Error # работаем с ошибкой, e.g. адрес слишком длинный puts "match.context # => #{match.context} \n\n" puts "render json: { errors: [#{match.unpack['message']}] } }" when BC::ContractFailure puts "Honeybadger.notify 'Unexpected behavior in Russian Post', context: #{match.context}" puts "render json: { errors: 'Ooops! Not working, we've been notified. Please, try again later' }" return unless ENV["RAISE"] match.errors.values.flatten.find do |v| raise v if StandardError === v end else raise end end puts "#{'=' * 20}================================#{'=' * 20}" puts "\n\n\n" puts "#{'=' * 20} WHEN VALID RESPONSE: #{'=' * 20}" valid_response = '{"cost": 1000, "cur": "RUB"}' match_response(valid_response) puts "#{'=' * 20}================================#{'=' * 20}" puts "\n\n\n" puts "#{'=' * 20} WHEN KNOWN API ERROR RESPONSE: #{'=' * 20}" error_response = '{"code": 123, "message": "Too Long Address"}' match_response(error_response) puts "#{'=' * 20}================================#{'=' * 20}" puts "ss => errors }\n\n\n" puts "#{'=' * 20} WHEN UNEXPECTED RESPONSE: #{'=' * 20}" invalid_response = "" match_response(invalid_response) puts "#{'=' * 20}================================#{'=' * 20}"