So, I love the active_model_serializers gem, but I encountered a really weird bug lately. I’m hoping it’s resolved in a future release. However, I’m having to migrate my project to another option in the meantime. I explored jbuilder, but I was disappointed by its lack of support for efficient layout rendering. The contributors can’t fix it without breaking backwards compatibility. Then, I looked at RABL, but the DSL seemed a little excessive for my needs. So, I looked back and decided that I really like serializers.

Could a developer write a magic-less serializer from scratch? Well, it turns out you can. As a matter of fact, it’s only 27 lines of ruby and requires no external gems. It also works with any hash-able object in ruby. Doesn’t even require it to be an ActiveModel.

require 'json'

class Serializer
def initialize(subject)
@subject = subject
@attrs = {}
@sanitized_hash = {}
end

def as_hash
@attrs.map do |k, v|
@sanitized_hash[k] = @subject[k] if v
end

@sanitized_hash
end

def as_json
as_hash.to_json
end

protected

def expose(*atts, iff: true)
atts.each do |att|
@attrs[att] = iff
end
end
end


Then, to create a specific serializer, simply declare a subclass and mark the properties to expose in the constructor.

class UserSerializer < Serializer
def initialize(subject)
super(subject)
expose :id
expose :name
expose :auth_token, :auth_token_expiration
end
end


It supports conditional serialization as well:

def show_auth_token_expiration?
false
end

class UserSerializer < Serializer
def initialize(subject)
super(subject)
expose :id, :name, :auth_token
expose :auth_token_expiration, iff: show_auth_token_expiration?
end
end


And here is an example of it being used:

render json: UserSerializer.new({
id: 1,
name: 'Hello',
auth_token: '2323',
auth_token_expiration: 'Dec 14, 1995',

{"id":1, "name": "Hello", "auth_token": "2323"}