summaryrefslogtreecommitdiff
path: root/rubocop/cop/usage_data/histogram_with_large_table.rb
blob: 961773df55cf1d4f78487f81eddc0be005f11d99 (plain)
1
2
3
4
5
6
7
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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# frozen_string_literal: true

module RuboCop
  module Cop
    module UsageData
      # This cop checks that histogram method is not used in usage_data.rb files
      # for models representing large tables, as defined by migration helpers.
      #
      # @example
      #
      # # bad
      # histogram(Issue, buckets: 1..100)
      # histogram(User.active, buckets: 1..100)
      class HistogramWithLargeTable < RuboCop::Cop::Cop
        MSG = 'Avoid histogram method on %{model_name}'

        # Match one level const as Issue, Gitlab
        def_node_matcher :one_level_node, <<~PATTERN
          (send nil? :histogram
            `(const {nil? cbase} $_)
          ...)
        PATTERN

        # Match two level const as ::Clusters::Cluster, ::Ci::Pipeline
        def_node_matcher :two_level_node, <<~PATTERN
          (send nil? :histogram
            `(const
              (const {nil? cbase} $_)
            $_)
          ...)
        PATTERN

        def on_send(node)
          one_level_matches = one_level_node(node)
          two_level_matches = two_level_node(node)

          return unless Array(one_level_matches).any? || Array(two_level_matches).any?

          class_name = two_level_matches ? two_level_matches.join('::').to_sym : one_level_matches

          if large_table?(class_name)
            add_offense(node, location: :expression, message: format(MSG, model_name: class_name))
          end
        end

        private

        def large_table?(model)
          high_traffic_models.include?(model.to_s)
        end

        def high_traffic_models
          cop_config['HighTrafficModels'] || []
        end
      end
    end
  end
end