Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'rubocop/cop/performance/ar_count_each.rb')
-rw-r--r--rubocop/cop/performance/ar_count_each.rb45
1 files changed, 45 insertions, 0 deletions
diff --git a/rubocop/cop/performance/ar_count_each.rb b/rubocop/cop/performance/ar_count_each.rb
new file mode 100644
index 00000000000..2fe8e549872
--- /dev/null
+++ b/rubocop/cop/performance/ar_count_each.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+module RuboCop
+ module Cop
+ module Performance
+ class ARCountEach < RuboCop::Cop::Cop
+ def message(ivar)
+ "If #{ivar} is AR relation, avoid `#{ivar}.count ...; #{ivar}.each... `, this will trigger two queries. " \
+ "Use `#{ivar}.load.size ...; #{ivar}.each... ` instead. If #{ivar} is an array, try to use #{ivar}.size."
+ end
+
+ def_node_matcher :count_match, <<~PATTERN
+ (send (ivar $_) :count)
+ PATTERN
+
+ def_node_matcher :each_match, <<~PATTERN
+ (send (ivar $_) :each)
+ PATTERN
+
+ def file_name(node)
+ node.location.expression.source_buffer.name
+ end
+
+ def in_haml_file?(node)
+ file_name(node).end_with?('.haml.rb')
+ end
+
+ def on_send(node)
+ return unless in_haml_file?(node)
+
+ ivar_count = count_match(node)
+ return unless ivar_count
+
+ node.each_ancestor(:begin) do |begin_node|
+ begin_node.each_descendant do |n|
+ ivar_each = each_match(n)
+
+ add_offense(node, location: :expression, message: message(ivar_count)) if ivar_each == ivar_count
+ end
+ end
+ end
+ end
+ end
+ end
+end