Module: Optic::Rails

Defined in:
lib/optic/rails.rb,
lib/optic/rails/railtie.rb,
lib/optic/rails/version.rb

Defined Under Namespace

Classes: Railtie

Constant Summary collapse

VERSION =
"1.3.3"

Class Method Summary collapse

Class Method Details

.entities(logger) ⇒ Object



8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/optic/rails.rb', line 8

def entities(logger)
  with_connection do
    {
      schema_version: ActiveRecord::Migrator.current_version,
      entities: active_record_klasses.map do |klass|
        begin
          logger.debug "Inspecting entity #{klass}"
          {
            name: klass.name,
            table_name: klass.table_name,
            entity_attribute_names: klass.attribute_names,
            table_exists: klass.table_exists?,
            associations: klass.reflect_on_all_associations.map do |reflection|
              begin
                logger.debug "Inspecting association #{klass}/#{reflection.name}"
                {
                  name: reflection.name,
                  macro: reflection.macro,
                  options: reflection.options.map { |k, v| [k, v.to_s] }.to_h,
                  klass_name: reflection.options[:polymorphic] ? nil : reflection.klass.name,
                }
              rescue
                nil
              end
            end.compact
          }
        rescue
          nil
        end
      end.compact
    }
  end
end

.metrics(logger, instructions) ⇒ Object



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/optic/rails.rb', line 42

def metrics(logger, instructions)
  with_connection do |connection|
    instructions.map do |instruction|
      logger.debug "Gathering metrics for metric_configuration_id = #{instruction['metric_configuration_id']}"
      name = instruction["entity"]
      entity = entity_for_entity_name name

      query =
        if pivot_name = instruction["pivot"]
          # TODO this is a terrible hack to extract zero-valued pivot
          # instances. The right thing to do is select from the pivot
          # table and LEFT OUTER JOIN to the entity table, which results
          # in a much simpler query, but it means we have to rewrite the
          # pathfinding logic in the server to find paths using has_many
          # associations instead of belongs_to associations, which might
          # be less accurate for a bunch of reasons. For now, we're doing
          # an INNER JOIN selecting from the entity table and then
          # selecting every possible pivot value as a UNION, throwing out
          # the duplicates.
          pivot = entity_for_entity_name pivot_name
          join_path = instruction["join_path"]
          joins = join_path.reverse.map(&:to_sym).inject { |acc, elt| { elt => acc } }

          columns = [
            %Q|#{qualified_primary_key(connection, pivot)} AS primary_key|,
            %Q|#{qualified_entity_column(connection, pivot, instruction["pivot_attribute_name"])} AS pivot_attribute_name|,
          ]

          join_select = entity
                        .joins(joins)
                        .group(qualified_primary_key(connection, pivot))
                        .select(*columns, 'COUNT(*) AS count')
                        .to_sql

          instance_select = pivot
                            .select(*columns, '0 AS count')
                            .to_sql

          union_sql = <<~"SQL"
                        SELECT pivot_values.primary_key, pivot_values.pivot_attribute_name, MAX(pivot_values.count) AS count
                          FROM (#{join_select} UNION ALL #{instance_select}) AS pivot_values
                          GROUP BY pivot_values.primary_key, pivot_values.pivot_attribute_name
                      SQL
        else
          entity.select('COUNT(*) as count').to_sql
        end

      { metric_configuration_id: instruction["metric_configuration_id"], result: connection.exec_query(query).to_a }
    end
  end
end