123456789_123456789_123456789_123456789_123456789_

Module: ActiveJob::Arguments

Relationships & Source Files
Defined in: activejob/lib/active_job/arguments.rb

Constant Summary

Instance Method Summary

Instance Method Details

#convert_to_global_id_hash(argument) (private)

[ GitHub ]

  
# File 'activejob/lib/active_job/arguments.rb', line 201

def convert_to_global_id_hash(argument)
  { GLOBALID_KEY => argument.to_global_id.to_s }
rescue URI::GID::MissingModelIdError
  raise SerializationError, "Unable to serialize #{argument.class} " \
    "without an id. (Maybe you forgot to call save?)"
end

#custom_serialized?(hash) ⇒ Boolean (private)

[ GitHub ]

  
# File 'activejob/lib/active_job/arguments.rb', line 148

def custom_serialized?(hash)
  hash.key?(OBJECT_SERIALIZER_KEY)
end

#deserialize(arguments)

Deserializes a set of arguments. Intrinsic types that can safely be deserialized without mutation are returned as-is. Arrays/Hashes are deserialized element by element. All other types are deserialized using GlobalID.

[ GitHub ]

  
# File 'activejob/lib/active_job/arguments.rb', line 42

def deserialize(arguments)
  arguments.map { |argument| deserialize_argument(argument) }
rescue
  raise DeserializationError
end

#deserialize_argument(argument) (private)

[ GitHub ]

  
# File 'activejob/lib/active_job/arguments.rb', line 119

def deserialize_argument(argument)
  case argument
  when nil, true, false, String, Integer, Float
    argument
  when BigDecimal # BigDecimal may have been legacy serialized; Remove in 7.2
    argument
  when Array
    argument.map { |arg| deserialize_argument(arg) }
  when Hash
    if serialized_global_id?(argument)
      deserialize_global_id argument
    elsif custom_serialized?(argument)
      Serializers.deserialize(argument)
    else
      deserialize_hash(argument)
    end
  else
    raise ArgumentError, "Can only deserialize primitive arguments: #{argument.inspect}"
  end
end

#deserialize_global_id(hash) (private)

[ GitHub ]

  
# File 'activejob/lib/active_job/arguments.rb', line 144

def deserialize_global_id(hash)
  GlobalID::Locator.locate hash[GLOBALID_KEY]
end

#deserialize_hash(serialized_hash) (private)

[ GitHub ]

  
# File 'activejob/lib/active_job/arguments.rb', line 158

def deserialize_hash(serialized_hash)
  result = serialized_hash.transform_values { |v| deserialize_argument(v) }
  if result.delete(WITH_INDIFFERENT_ACCESS_KEY)
    result = result.with_indifferent_access
  elsif symbol_keys = result.delete(SYMBOL_KEYS_KEY)
    result = transform_symbol_keys(result, symbol_keys)
  elsif symbol_keys = result.delete(RUBY2_KEYWORDS_KEY)
    result = transform_symbol_keys(result, symbol_keys)
    result = Hash.ruby2_keywords_hash(result)
  end
  result
end

#serialize(arguments)

Serializes a set of arguments. Intrinsic types that can safely be serialized without mutation are returned as-is. Arrays/Hashes are serialized element by element. All other types are serialized using GlobalID.

[ GitHub ]

  
# File 'activejob/lib/active_job/arguments.rb', line 34

def serialize(arguments)
  arguments.map { |argument| serialize_argument(argument) }
end

#serialize_argument(argument) (private)

[ GitHub ]

  
# File 'activejob/lib/active_job/arguments.rb', line 71

def serialize_argument(argument)
  case argument
  when nil, true, false, Integer, Float # Types that can hardly be subclassed
    argument
  when String
    if argument.class == String
      argument
    else
      begin
        Serializers.serialize(argument)
      rescue SerializationError
        argument
      end
    end
  when GlobalID::Identification
    convert_to_global_id_hash(argument)
  when Array
    argument.map { |arg| serialize_argument(arg) }
  when ActiveSupport::HashWithIndifferentAccess
    serialize_indifferent_hash(argument)
  when Hash
    symbol_keys = argument.each_key.grep(Symbol).map!(&:to_s)
    aj_hash_key = if Hash.ruby2_keywords_hash?(argument)
      RUBY2_KEYWORDS_KEY
    else
      SYMBOL_KEYS_KEY
    end
    result = serialize_hash(argument)
    result[aj_hash_key] = symbol_keys
    result
  else
    if argument.respond_to?(:permitted?) && argument.respond_to?(:to_h)
      serialize_indifferent_hash(argument.to_h)
    elsif BigDecimal === argument && !ActiveJob.use_big_decimal_serializer
      ActiveJob.deprecator.warn(<<~MSG)
        Primitive serialization of BigDecimal job arguments is deprecated as it may serialize via .to_s using certain queue adapters.
        Enable config.active_job.use_big_decimal_serializer to use BigDecimalSerializer instead, which will be mandatory in Rails 7.2.

        Note that if your application has multiple replicas, you should only enable this setting after successfully deploying your app to Rails 7.1 first.
        This will ensure that during your deployment all replicas are capable of deserializing arguments serialized with BigDecimalSerializer.
      MSG
      argument
    else
      Serializers.serialize(argument)
    end
  end
end

#serialize_hash(argument) (private)

[ GitHub ]

  
# File 'activejob/lib/active_job/arguments.rb', line 152

def serialize_hash(argument)
  argument.each_with_object({}) do |(key, value), hash|
    hash[serialize_hash_key(key)] = serialize_argument(value)
  end
end

#serialize_hash_key(key) (private)

[ GitHub ]

  
# File 'activejob/lib/active_job/arguments.rb', line 171

def serialize_hash_key(key)
  case key
  when *RESERVED_KEYS
    raise SerializationError.new("Can't serialize a Hash with reserved key #{key.inspect}")
  when String, Symbol
    key.to_s
  else
    raise SerializationError.new("Only string and symbol hash keys may be serialized as job arguments, but #{key.inspect} is a #{key.class}")
  end
end

#serialize_indifferent_hash(indifferent_hash) (private)

[ GitHub ]

  
# File 'activejob/lib/active_job/arguments.rb', line 182

def serialize_indifferent_hash(indifferent_hash)
  result = serialize_hash(indifferent_hash)
  result[WITH_INDIFFERENT_ACCESS_KEY] = serialize_argument(true)
  result
end

#serialized_global_id?(hash) ⇒ Boolean (private)

[ GitHub ]

  
# File 'activejob/lib/active_job/arguments.rb', line 140

def serialized_global_id?(hash)
  hash.size == 1 && hash.include?(GLOBALID_KEY)
end

#transform_symbol_keys(hash, symbol_keys) (private)

[ GitHub ]

  
# File 'activejob/lib/active_job/arguments.rb', line 188

def transform_symbol_keys(hash, symbol_keys)
  # NOTE: HashWithIndifferentAccess#transform_keys always
  # returns stringified keys with indifferent access
  # so we call #to_h here to ensure keys are symbolized.
  hash.to_h.transform_keys do |key|
    if symbol_keys.include?(key)
      key.to_sym
    else
      key
    end
  end
end