aboutsummaryrefslogtreecommitdiffstats
path: root/activejob/lib/active_job/arguments.rb
diff options
context:
space:
mode:
authorJeremy Kemper <jeremykemper@gmail.com>2014-09-14 19:34:17 -0700
committerJeremy Kemper <jeremykemper@gmail.com>2014-09-25 10:00:19 -0700
commit3f1d04e3bb04d240792112b5b45a9062c72e0df4 (patch)
treeb7843061a6b5149d405a93ec30d642851fb0d3a4 /activejob/lib/active_job/arguments.rb
parent391cfc20546049e056b99f8e47be92799412ef78 (diff)
downloadrails-3f1d04e3bb04d240792112b5b45a9062c72e0df4.tar.gz
rails-3f1d04e3bb04d240792112b5b45a9062c72e0df4.tar.bz2
rails-3f1d04e3bb04d240792112b5b45a9062c72e0df4.zip
Fix string/gid collision in job arguments
Serialize Global IDs as special objects, distinguishable from Strings
Diffstat (limited to 'activejob/lib/active_job/arguments.rb')
-rw-r--r--activejob/lib/active_job/arguments.rb30
1 files changed, 27 insertions, 3 deletions
diff --git a/activejob/lib/active_job/arguments.rb b/activejob/lib/active_job/arguments.rb
index 099ea4d169..86b85ebdba 100644
--- a/activejob/lib/active_job/arguments.rb
+++ b/activejob/lib/active_job/arguments.rb
@@ -35,12 +35,15 @@ module ActiveJob
end
private
+ GLOBALID_KEY = '_aj_globalid'.freeze
+ private_constant :GLOBALID_KEY
+
def serialize_argument(argument)
case argument
when *TYPE_WHITELIST
argument
when GlobalID::Identification
- argument.to_global_id.to_s
+ { GLOBALID_KEY => argument.to_global_id.to_s }
when Array
argument.map { |arg| serialize_argument(arg) }
when Hash
@@ -61,16 +64,37 @@ module ActiveJob
when Array
argument.map { |arg| deserialize_argument(arg) }
when Hash
- argument.each_with_object({}.with_indifferent_access) do |(key, value), hash|
- hash[key] = deserialize_argument(value)
+ if serialized_global_id?(argument)
+ deserialize_global_id argument
+ else
+ deserialize_hash argument
end
else
raise ArgumentError, "Can only deserialize primitive arguments: #{argument.inspect}"
end
end
+ def serialized_global_id?(hash)
+ hash.size == 1 and hash.include?(GLOBALID_KEY)
+ end
+
+ def deserialize_global_id(hash)
+ GlobalID::Locator.locate hash[GLOBALID_KEY]
+ end
+
+ def deserialize_hash(serialized_hash)
+ serialized_hash.each_with_object({}.with_indifferent_access) do |(key, value), hash|
+ hash[key] = deserialize_argument(value)
+ end
+ end
+
+ RESERVED_KEYS = [GLOBALID_KEY, GLOBALID_KEY.to_sym]
+ private_constant :RESERVED_KEYS
+
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