diff options
author | Rafael Mendonça França <rafaelmfranca@gmail.com> | 2018-02-09 15:23:05 -0500 |
---|---|---|
committer | Rafael Mendonça França <rafaelmfranca@gmail.com> | 2018-02-14 13:10:07 -0500 |
commit | ea615332452e6860872020aa161c5d34e81f1eea (patch) | |
tree | 2ba5478b1e48b56f722aed17c3f6d2d5f9d1d7d9 /activejob/lib | |
parent | 9bc8b4bbde4634e0e4bddcffa25e0bf8d74d19cd (diff) | |
download | rails-ea615332452e6860872020aa161c5d34e81f1eea.tar.gz rails-ea615332452e6860872020aa161c5d34e81f1eea.tar.bz2 rails-ea615332452e6860872020aa161c5d34e81f1eea.zip |
Only add one more custom key in the serialized hash
Now custom serialziers can register itself in the serialized hash using
the "_aj_serialized" key that constains the serializer name.
This way we can avoid poluting the hash with many reserved keys.
Diffstat (limited to 'activejob/lib')
5 files changed, 36 insertions, 43 deletions
diff --git a/activejob/lib/active_job/serializers.rb b/activejob/lib/active_job/serializers.rb index 41113c521c..12458ea572 100644 --- a/activejob/lib/active_job/serializers.rb +++ b/activejob/lib/active_job/serializers.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +require "set" + module ActiveJob # Raised when an exception is raised during job arguments deserialization. # @@ -34,7 +36,7 @@ module ActiveJob autoload :StandardTypeSerializer mattr_accessor :_additional_serializers - self._additional_serializers = [] + self._additional_serializers = Set.new class << self # Returns serialized representative of the passed object. @@ -62,27 +64,32 @@ module ActiveJob # Adds a new serializer to a list of known serializers def add_serializers(*new_serializers) - check_duplicate_serializer_keys!(new_serializers) - - self._additional_serializers = new_serializers + self._additional_serializers + self._additional_serializers += new_serializers end # Returns a list of reserved keys, which cannot be used as keys for a hash def reserved_serializers_keys - serializers.select { |s| s.respond_to?(:key) }.map(&:key) + RESERVED_KEYS end - - private - - def check_duplicate_serializer_keys!(serializers) - keys_to_add = serializers.select { |s| s.respond_to?(:key) }.map(&:key) - - duplicate_keys = reserved_serializers_keys & keys_to_add - - raise ArgumentError.new("Can't add serializers because of keys duplication: #{duplicate_keys}") if duplicate_keys.any? - end end + # :nodoc: + GLOBALID_KEY = "_aj_globalid".freeze + # :nodoc: + SYMBOL_KEYS_KEY = "_aj_symbol_keys".freeze + # :nodoc: + WITH_INDIFFERENT_ACCESS_KEY = "_aj_hash_with_indifferent_access".freeze + # :nodoc: + OBJECT_SERIALIZER_KEY = "_aj_serialized" + + # :nodoc: + RESERVED_KEYS = [ + GLOBALID_KEY, GLOBALID_KEY.to_sym, + SYMBOL_KEYS_KEY, SYMBOL_KEYS_KEY.to_sym, + WITH_INDIFFERENT_ACCESS_KEY, WITH_INDIFFERENT_ACCESS_KEY.to_sym, + ] + private_constant :RESERVED_KEYS + add_serializers GlobalIDSerializer, StandardTypeSerializer, HashWithIndifferentAccessSerializer, diff --git a/activejob/lib/active_job/serializers/global_id_serializer.rb b/activejob/lib/active_job/serializers/global_id_serializer.rb index ec20cf04f7..84ed33ef99 100644 --- a/activejob/lib/active_job/serializers/global_id_serializer.rb +++ b/activejob/lib/active_job/serializers/global_id_serializer.rb @@ -4,21 +4,21 @@ module ActiveJob module Serializers # Provides methods to serialize and deserialize objects which mixes `GlobalID::Identification`, # including `ActiveRecord::Base` models - class GlobalIDSerializer < ObjectSerializer + class GlobalIDSerializer < BaseSerializer class << self def serialize(object) - { key => object.to_global_id.to_s } + { GLOBALID_KEY => object.to_global_id.to_s } rescue URI::GID::MissingModelIdError raise SerializationError, "Unable to serialize #{object.class} " \ "without an id. (Maybe you forgot to call save?)" end def deserialize(hash) - GlobalID::Locator.locate(hash[key]) + GlobalID::Locator.locate(hash[GLOBALID_KEY]) end - def key - "_aj_globalid" + def deserialize?(argument) + argument.is_a?(Hash) && argument[GLOBALID_KEY] end private diff --git a/activejob/lib/active_job/serializers/hash_serializer.rb b/activejob/lib/active_job/serializers/hash_serializer.rb index ca39a81ae9..2bbb31946d 100644 --- a/activejob/lib/active_job/serializers/hash_serializer.rb +++ b/activejob/lib/active_job/serializers/hash_serializer.rb @@ -23,12 +23,12 @@ module ActiveJob transform_symbol_keys(result, symbol_keys) end + private + def key - "_aj_symbol_keys" + SYMBOL_KEYS_KEY end - private - def serialize_hash(hash) hash.each_with_object({}) do |(key, value), result| result[serialize_hash_key(key)] = Serializers.serialize(value) diff --git a/activejob/lib/active_job/serializers/hash_with_indifferent_access_serializer.rb b/activejob/lib/active_job/serializers/hash_with_indifferent_access_serializer.rb index b0fb29d58b..af3576dd57 100644 --- a/activejob/lib/active_job/serializers/hash_with_indifferent_access_serializer.rb +++ b/activejob/lib/active_job/serializers/hash_with_indifferent_access_serializer.rb @@ -12,22 +12,18 @@ module ActiveJob result end - def deserialize?(argument) - argument.is_a?(Hash) && argument[key] - end - def deserialize(hash) result = hash.transform_values { |v| Serializers.deserialize(v) } result.delete(key) result.with_indifferent_access end + private + def key - "_aj_hash_with_indifferent_access" + WITH_INDIFFERENT_ACCESS_KEY end - private - def klass ActiveSupport::HashWithIndifferentAccess end diff --git a/activejob/lib/active_job/serializers/object_serializer.rb b/activejob/lib/active_job/serializers/object_serializer.rb index 075360b26e..d5ff8c91f1 100644 --- a/activejob/lib/active_job/serializers/object_serializer.rb +++ b/activejob/lib/active_job/serializers/object_serializer.rb @@ -4,22 +4,12 @@ module ActiveJob module Serializers class ObjectSerializer < BaseSerializer class << self - def serialize(object) - { key => object.class.name } + def serialize(hash) + { OBJECT_SERIALIZER_KEY => self.name }.merge!(hash) end def deserialize?(argument) - argument.respond_to?(:keys) && argument.keys == keys - end - - def deserialize(hash) - hash[key].constantize - end - - private - - def keys - [key] + argument.is_a?(Hash) && argument[OBJECT_SERIALIZER_KEY] == self.name end end end |