[colug-432] deserialize objects in Ruby
richardjhornsby at gmail.com
Wed Sep 30 11:00:38 EDT 2015
Thought I'd share what I came up with as a working solution, although its elegance is questionable. I haven't been able to find any other references to this problem on the Interwebs, although it has to be out there.
The problem is that when you deserialize Dog, Dog.initialize was being called with the set (or a subset) of arguments first passed into self.json_create(*o). Dog.initialize() calls super - Animal.initialize() - with that same exact set of arguments. Animals and dogs have a different constructors, different properties, and thus need a different set (and different number) of arguments.
Dog.json_create(*o) -> Dog.initialize(bark) -> Animal.initialize(bark)
That doesn't work properly because the first enumerated argument to Animal is has_fur. Alternatively, if you cater to Animal:
Dog.json_create(*o) -> Dog.initialize(has_fur, color, name) -> Animal.initialize(has_fur, color, name)
or, passing *o directly through gives us:
Dog.json_create(*o) -> Dog.initialize(has_fur, color, name, bark) -> Animal.initialize(has_fur, color, name, bark)
Now Dog is taking the first argument has_fur, and applying that to the bark property, because Dog's first and only constructor argument is 'bark'. (That also means Dog.initialize must allow passing at least the number of arguments Animal.initialize expects...). It's a confusing mess.
The solution I came up with is to forgo enumerated arguments and instead pass a hash of properties out of json_create. The respective initialize method now takes just 1 argument (instead of a variable number), has access to all properties, but only looks at the ones it needs.
Hopefully this helps someone else. The pattern seems like it could be applicable to other OO languages.
Final working result:
More information about the colug-432