# frozen_string_literal: true require 'json' # rubocop:disable Metrics/BlockLength because this is how an ActiveSupport # concern looks like module Immoscout module Models module Concerns # Includes functionality to serialize a Ruby model properly. module Renderable extend ActiveSupport::Concern included do def as_json wrapped? ? to_json_wrapped : to_json_unwrapped end def to_json(*) as_json.to_json end alias_method :to_s, :to_json protected def wrapped? self.class.try(:json_wrapper) end # rubocop:disable Metrics/PerceivedComplexity because this is the # bare minimum logic # rubocop:disable Metrics/MethodLength dito # rubocop:disable Metrics/CyclomaticComplexity dito # rubocop:disable Metrics/AbcSize dito def to_h self.class.properties.each_with_object({}) do |(key, value), memo| # skip if it's readonly and should not be exposed in #as_json readonly = value.fetch(:readonly, false) next if readonly.try(:call, self) || readonly == true # use :alias instead of key as json-key property = value.fetch(:alias, key) # use :default if present AND value is nil rendered = send(key) || value.fetch(:default, nil) memo[property] = \ if rendered.is_a?(Array) rendered.map do |elem| elem.try(:as_json) || elem end else rendered.try(:as_json) || rendered end memo end end # rubocop:enable Metrics/PerceivedComplexity # rubocop:enable Metrics/MethodLength # rubocop:enable Metrics/CyclomaticComplexity # rubocop:enable Metrics/AbcSize def to_json_wrapped { self.class.try(:json_wrapper) => to_json_unwrapped } end def to_json_unwrapped to_h .compact .stringify_keys .deep_transform_keys { |key| key.camelize :lower } end end end end end end # rubocop:enable Metrics/BlockLength