Skip to content

Instantly share code, notes, and snippets.

@vol1ura
Created May 14, 2022 17:50
Show Gist options
  • Save vol1ura/7952afcf1c428fc014939d29ab3efa40 to your computer and use it in GitHub Desktop.
Save vol1ura/7952afcf1c428fc014939d29ab3efa40 to your computer and use it in GitHub Desktop.
A simple "replacement" for `grape-entity` gem for small API projects. Allows you to create custom classes, inherit from them and get representations of both individual objects and their collections.
# frozen_string_literal: true
module Entities
# Fabric class to build object representation classes
class Base
def self.represent(...)
new(...).represent
end
def self.represent_collection(collection, options = {})
collection.map { |object| represent(object, options) }
end
def initialize(object, exposed_keys, options)
@object = object
@model_keys = exposed_keys.keys
@mapping = exposed_keys
@options = options
end
def represent
@options.key?(:root) ? { @options[:root] => body } : body
end
private
attr_reader :object
def body
@body ||= model_keys.index_with { |key| build_value(key) }.compact
end
def model_keys
@model_keys &= Array(@options[:only]) if @options.key? :only
@model_keys -= Array(@options[:except]) if @options.key? :except
@model_keys
end
def build_value(key)
key_method = @mapping.dig(key, :as).presence || key
value = key_method.is_a?(Proc) ? call_to_proc(key_method) : send_to_self(key_method)
return if @mapping.dig(key, :expose_nil) == false && value.blank?
value = @mapping[key][:format_with].to_proc.call(value) if @mapping.dig(key, :format_with)
value
end
def send_to_self(key_method)
respond_to?(key_method, true) ? send(key_method) : object.public_send(key_method)
end
def call_to_proc(key_method)
key_method.arity.zero? ? key_method.call : key_method.call(object)
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment