Simplify the implementation of custom serialziers

Right now it is only possible to define serializers globally so we don't
need to use a class attribute in the job class.
This commit is contained in:
Rafael Mendonça França 2018-02-09 14:24:55 -05:00
parent 3785a57299
commit ec686a471e
3 changed files with 37 additions and 41 deletions

View File

@ -33,16 +33,31 @@ module ActiveJob
autoload :ObjectSerializer
autoload :StandardTypeSerializer
included do
class_attribute :_additional_serializers, instance_accessor: false, instance_predicate: false
self._additional_serializers = []
end
mattr_accessor :_additional_serializers
self._additional_serializers = []
class << self
# Returns serialized representative of the passed object.
# Will look up through all known serializers.
# Raises `ActiveJob::SerializationError` if it can't find a proper serializer.
def serialize(argument)
serializer = serializers.detect { |s| s.serialize?(argument) }
raise SerializationError.new("Unsupported argument type: #{argument.class.name}") unless serializer
serializer.serialize(argument)
end
# Returns deserialized object.
# Will look up through all known serializers.
# If no serializers found will raise `ArgumentError`
def deserialize(argument)
serializer = serializers.detect { |s| s.deserialize?(argument) }
raise ArgumentError, "Can only deserialize primitive arguments: #{argument.inspect}" unless serializer
serializer.deserialize(argument)
end
# Includes the method to list known serializers and to add new ones
module ClassMethods
# Returns list of known serializers
def serializers
self._additional_serializers + ActiveJob::Serializers::SERIALIZERS
self._additional_serializers
end
# Adds a new serializer to a list of known serializers
@ -68,33 +83,10 @@ module ActiveJob
end
end
# :nodoc:
SERIALIZERS = [
::ActiveJob::Serializers::GlobalIDSerializer,
::ActiveJob::Serializers::StandardTypeSerializer,
::ActiveJob::Serializers::HashWithIndifferentAccessSerializer,
::ActiveJob::Serializers::HashSerializer,
::ActiveJob::Serializers::ArraySerializer
].freeze
class << self
# Returns serialized representative of the passed object.
# Will look up through all known serializers.
# Raises `ActiveJob::SerializationError` if it can't find a proper serializer.
def serialize(argument)
serializer = ::ActiveJob::Base.serializers.detect { |s| s.serialize?(argument) }
raise SerializationError.new("Unsupported argument type: #{argument.class.name}") unless serializer
serializer.serialize(argument)
end
# Returns deserialized object.
# Will look up through all known serializers.
# If no serializers found will raise `ArgumentError`
def deserialize(argument)
serializer = ::ActiveJob::Base.serializers.detect { |s| s.deserialize?(argument) }
raise ArgumentError, "Can only deserialize primitive arguments: #{argument.inspect}" unless serializer
serializer.deserialize(argument)
end
end
add_serializers GlobalIDSerializer,
StandardTypeSerializer,
HashWithIndifferentAccessSerializer,
HashSerializer,
ArraySerializer
end
end

View File

@ -38,7 +38,7 @@ module ActiveJob
def serialize_hash_key(key)
raise SerializationError.new("Only string and symbol hash keys may be serialized as job arguments, but #{key.inspect} is a #{key.class}") unless [String, Symbol].include?(key.class)
raise SerializationError.new("Can't serialize a Hash with reserved key #{key.inspect}") if ActiveJob::Base.reserved_serializers_keys.include?(key.to_s)
raise SerializationError.new("Can't serialize a Hash with reserved key #{key.inspect}") if ActiveJob::Serializers.reserved_serializers_keys.include?(key.to_s)
key.to_s
end

View File

@ -36,7 +36,11 @@ class SerializersTest < ActiveSupport::TestCase
setup do
@value_object = DummyValueObject.new 123
ActiveJob::Base._additional_serializers = []
@original_serializers = ActiveJob::Serializers.serializers
end
teardown do
ActiveJob::Serializers._additional_serializers = @original_serializers
end
test "can't serialize unknown object" do
@ -51,14 +55,14 @@ class SerializersTest < ActiveSupport::TestCase
end
test "adds new serializer" do
ActiveJob::Base.add_serializers DummySerializer
assert ActiveJob::Base.serializers.include?(DummySerializer)
ActiveJob::Serializers.add_serializers DummySerializer
assert ActiveJob::Serializers.serializers.include?(DummySerializer)
end
test "can't add serializer with the same key twice" do
ActiveJob::Base.add_serializers DummySerializer
ActiveJob::Serializers.add_serializers DummySerializer
assert_raises ArgumentError do
ActiveJob::Base.add_serializers DummySerializer
ActiveJob::Serializers.add_serializers DummySerializer
end
end
end