Introduce an abstract serializer class
nesaulov opened this issue · 7 comments
I think that in most of the cases the logic of serialization should be separated from the model itself. So I suggest having a class that will represent abstract serializer which will be inherited by particular ones. API that I propose:
class HumanSerializer < Surrealist::Serializer
json_schema do
{ name: String, name_length: Integer }
end
def name_length
name.length
end
end
class Human
include Surrealist
attr_reader :name
surrealize_with HumanSerializer
def initialize(name)
@name = name
end
end
And two ways of serializing:
- Implicit (through DSL):
Human.new('John').surrealize(camelize: true)
# => '{"name": "John", "nameLength": 4}'
- Explicit:
HumanSerializer.new(Human.new('Alfred')).surrealize(camelize: true)
# => '{"name": "Alfred", "nameLength": 6}'
@AlessandroMinali what do you think?
Yea the idea behind this separation of concerns makes sense to me. I'd like less repetition and further complete separation. I'm not sure how much complexity it would add to have it just so the model would just be:
class Human
include HumanSerializer
attr_reader :name
def initialize(name)
@name = name
end
end
and still have the same api you mentioned.
EDIT: I can see the benefit of having an explicit call of what is being used to serialize though, less magic I suppose.
I think that
class Human
include HumanSerializer
is kind of counterintuitive and contradicts the separation of concerns principle. As for me, when I see include
I think of multiple inheritance in sense of adding methods to the object. Here, on the other hand we just need to delegate serialization logic to a separate object.
As for APIs, I suggest having both ways (explicit & implicit) available. I personally prefer explicit way over implicit, but I think for many people ease of use is preferable over explicitness ¯_(ツ)_/¯
Makes sense to me what you're saying. We should definitely have an explicit way to allow one off calls to other serializers and to potentially override what is defined in the object for that single explicit call.
Hi guys!
I think we can use multiple serializers for one model. I suggest that:
class HumanSerializer < Surrealist::Serializer
json_schema do
{ name: String, name_length: Integer }
end
def name_length
name.length
end
end
class SmallHumanSerializer < Surrealist::Serializer
json_schema do
{ name: String }
end
end
class Human
include Surrealist
attr_reader :name
surrealize_with HumanSerializer # default
surrealize_with SmallHumanSerializer, tag: :small
def initialize(name)
@name = name
end
end
# default behaviour
Human.new('John').surrealize(camelize: true)
# => '{"name": "John", "nameLength": 4}'
# using tags
Human.new('John').surrealize(camelize: true, tag: :small)
# => '{"name": "John"}'
Alright, closing this.