Skip to content

Commit 7766225

Browse files
author
Robert Mosolgo
authored
Merge pull request rmosolgo#3057 from rmosolgo/improve-serialize-timestamp-openstruct
Support Date, Time, and OpenStruct in Subscription::Serialize
2 parents 476b0e2 + 8160028 commit 7766225

File tree

2 files changed

+40
-4
lines changed

2 files changed

+40
-4
lines changed

lib/graphql/subscriptions/serialize.rb

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ module Serialize
99
GLOBALID_KEY = "__gid__"
1010
SYMBOL_KEY = "__sym__"
1111
SYMBOL_KEYS_KEY = "__sym_keys__"
12+
TIMESTAMP_KEY = "__timestamp__"
13+
TIMESTAMP_FORMAT = "%Y-%m-%d %H:%M:%S.%N%Z" # eg '2020-01-01 23:59:59.123456789+05:00'
14+
OPEN_STRUCT_KEY = "__ostruct__"
1215

1316
module_function
1417

@@ -55,10 +58,20 @@ def load_value(value)
5558
if value.is_a?(Array)
5659
value.map{|item| load_value(item)}
5760
elsif value.is_a?(Hash)
58-
if value.size == 1 && value.key?(GLOBALID_KEY)
59-
GlobalID::Locator.locate(value[GLOBALID_KEY])
60-
elsif value.size == 1 && value.key?(SYMBOL_KEY)
61-
value[SYMBOL_KEY].to_sym
61+
if value.size == 1
62+
case value.keys.first # there's only 1 key
63+
when GLOBALID_KEY
64+
GlobalID::Locator.locate(value[GLOBALID_KEY])
65+
when SYMBOL_KEY
66+
value[SYMBOL_KEY].to_sym
67+
when TIMESTAMP_KEY
68+
timestamp_class_name, timestamp_s = value[TIMESTAMP_KEY]
69+
timestamp_class = Object.const_get(timestamp_class_name)
70+
timestamp_class.strptime(timestamp_s, TIMESTAMP_FORMAT)
71+
when OPEN_STRUCT_KEY
72+
ostruct_values = load_value(value[OPEN_STRUCT_KEY])
73+
OpenStruct.new(ostruct_values)
74+
end
6275
else
6376
loaded_h = {}
6477
sym_keys = value.fetch(SYMBOL_KEYS_KEY, [])
@@ -101,6 +114,11 @@ def dump_value(obj)
101114
{ SYMBOL_KEY => obj.to_s }
102115
elsif obj.respond_to?(:to_gid_param)
103116
{GLOBALID_KEY => obj.to_gid_param}
117+
elsif obj.is_a?(Date) || obj.is_a?(Time)
118+
# DateTime extends Date; for TimeWithZone, call `.utc` first.
119+
{ TIMESTAMP_KEY => [obj.class.name, obj.strftime(TIMESTAMP_FORMAT)] }
120+
elsif obj.is_a?(OpenStruct)
121+
{ OPEN_STRUCT_KEY => dump_value(obj.to_h) }
104122
else
105123
obj
106124
end

spec/graphql/subscriptions/serialize_spec.rb

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,4 +46,22 @@ def serialize_load(v)
4646
loaded = serialize_load(dumped)
4747
assert_equal value, loaded
4848
end
49+
50+
it "can deserialize date/times" do
51+
datetime = DateTime.parse("2020-01-03 10:11:12")
52+
time = Time.new
53+
date = Date.today
54+
[datetime, time, date].each do |timestamp|
55+
serialized = serialize_dump(timestamp)
56+
reloaded = serialize_load(serialized)
57+
assert_equal timestamp, reloaded, "#{timestamp.inspect} is serialized to #{serialized.inspect} and reloaded"
58+
end
59+
end
60+
61+
it "can deserialize openstructs" do
62+
os = OpenStruct.new(a: 1.2, b: :c, d: Time.new, e: OpenStruct.new(f: [1, 2, 3]))
63+
serialized = serialize_dump(os)
64+
reloaded = serialize_load(serialized)
65+
assert_equal os, reloaded, "It reloads #{os.inspect} from #{serialized.inspect}"
66+
end
4967
end

0 commit comments

Comments
 (0)