|
| 1 | +# frozen_string_literal: true |
| 2 | + |
| 3 | +require 'active_support/concern' |
| 4 | + |
| 5 | +module Unity |
| 6 | + module Modules |
| 7 | + # You could use this module for service objects |
| 8 | + # class YourServiceObject |
| 9 | + # include Helpers::EntitiesLogDump |
| 10 | + # |
| 11 | + # You can get array of logged entities by custom attributes like that: |
| 12 | + # def topic_query |
| 13 | + # @topic_query ||= Topic.first(2) |
| 14 | + # end |
| 15 | + # |
| 16 | + # def foo |
| 17 | + # dump_entities(topic_query, attributes: [:id, :headline]) |
| 18 | + # end |
| 19 | + # Result: [{ "id" => 1, "headline" => "foo" }, { "id" => 2, "headline" => "bar" }] |
| 20 | + # |
| 21 | + module EntitiesLogDump |
| 22 | + extend ::ActiveSupport::Concern |
| 23 | + |
| 24 | + # @param entities [ActiveRecord::Relation,Array<Mongoid::Document>] |
| 25 | + # @param [Hash] options |
| 26 | + # @option options [Array<Symbol>] :attributes |
| 27 | + # @option options [Integer] :batch_size |
| 28 | + # @return [Array<Hash>] |
| 29 | + def dump_entities(entities, options = {}) |
| 30 | + attributes = options[:attributes] || all_attributes(entities.first) |
| 31 | + batch_size = options[:batch_size] || 100 |
| 32 | + |
| 33 | + dump_entities = [] |
| 34 | + entities.each_slice(batch_size) do |sliced_entities| |
| 35 | + sliced_entities.each do |entity| |
| 36 | + dump_entities.append(dump_entity(entity, attributes: attributes)) |
| 37 | + end |
| 38 | + end |
| 39 | + |
| 40 | + dump_entities |
| 41 | + end |
| 42 | + |
| 43 | + # @param entity [ApplicationRecord,Mongoid::Document] |
| 44 | + # @param [Hash] options |
| 45 | + # @option options [Array<Symbol>] :attributes |
| 46 | + # @return [Hash] |
| 47 | + def dump_entity(entity, options = {}) |
| 48 | + attributes = options[:attributes] || all_attributes(entity) |
| 49 | + attributes.map { |a| { a => try_array(entity.send(a)) } }.inject(:merge).deep_stringify_keys |
| 50 | + end |
| 51 | + |
| 52 | + # @param entity [ApplicationRecord,Mongoid::Document] |
| 53 | + # @return [Array<String,Symbol>] |
| 54 | + def all_attributes(entity) |
| 55 | + return entity.class.attribute_names if object_is_a?(entity, 'ApplicationRecord') |
| 56 | + return entity.fields.keys if object_is_a?(entity, 'Mongoid::Document') |
| 57 | + |
| 58 | + raise ArgumentError, "Can't determine full attributes list for this kind of entity." |
| 59 | + end |
| 60 | + |
| 61 | + private |
| 62 | + |
| 63 | + # @item [Object] |
| 64 | + # @return |
| 65 | + def try_array(item) |
| 66 | + return item.map { |i| i.try(:attributes) || i } if item.is_a?(Array) |
| 67 | + return item.map(&:attributes) if item.try(:any?) { |obj| object_is_a?(obj, 'ActiveRecord::Base') } |
| 68 | + |
| 69 | + item |
| 70 | + end |
| 71 | + |
| 72 | + # @param obj [Object] |
| 73 | + # @klass_name [String] |
| 74 | + # @return [Boolean] |
| 75 | + def object_is_a?(obj, klass_name) |
| 76 | + ancestors = obj.class.ancestors.map(&:to_s) |
| 77 | + ancestors.include?(klass_name) |
| 78 | + end |
| 79 | + end |
| 80 | + end |
| 81 | +end |
0 commit comments