2018-02-07 18:02:59 -08:00

91 lines
2.5 KiB
Ruby

# Usage:
# class Movie
# def to_json(payload)
# FastJsonapi::MultiToJson.to_json(payload)
# end
# end
module FastJsonapi
module MultiToJson
# Result object pattern is from https://johnnunemaker.com/resilience-in-ruby/
# e.g. https://github.com/github/github-ds/blob/fbda5389711edfb4c10b6c6bad19311dfcb1bac1/lib/github/result.rb
class Result
def initialize(*rescued_exceptions)
rescued_exceptions = [StandardError] if rescued_exceptions.empty?
@value = yield
@error = nil
rescue *rescued_exceptions => e
@error = e
end
def ok?
@error.nil?
end
def value!
if ok?
@value
else
raise @error
end
end
def rescue
return self if ok?
Result.new { yield(@error) }
end
end
def self.logger(device=nil)
return @logger = Logger.new(device) if device
@logger ||= Logger.new(IO::NULL)
end
# Encoder-compatible with default MultiJSON adapters and defaults
def self.to_json_method
encode_method = String.new(%(def _fast_to_json(object)\n ))
encode_method << Result.new(LoadError) {
require 'oj'
%(::Oj.dump(object, mode: :compat, time_format: :ruby, use_to_json: true))
}.rescue {
require 'yajl'
%(::Yajl::Encoder.encode(object))
}.rescue {
require 'jrjackson' unless defined?(::JrJackson)
%(::JrJackson::Json.dump(object))
}.rescue {
require 'json'
%(JSON.fast_generate(object, create_additions: false, quirks_mode: true))
}.rescue {
require 'gson'
%(::Gson::Encoder.new({}).encode(object))
}.rescue {
require 'active_support/json/encoding'
%(::ActiveSupport::JSON.encode(object))
}.rescue {
warn "No JSON encoder found. Falling back to `object.to_json`"
%(object.to_json)
}.value!
encode_method << "\nend"
end
def self.to_json(object)
_fast_to_json(object)
rescue NameError
define_to_json(FastJsonapi::MultiToJson)
_fast_to_json(object)
end
def self.define_to_json(receiver)
cl = caller_locations[0]
method_body = to_json_method
logger.debug { "Defining #{receiver}._fast_to_json as #{method_body.inspect}" }
receiver.instance_eval method_body, cl.absolute_path, cl.lineno
end
def self.reset_to_json!
undef :_fast_to_json if method_defined?(:_fast_to_json)
logger.debug { "Undefining #{receiver}._fast_to_json" }
end
end
end