-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
Add new cop Style/CollectionQuerying
#14288
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add new cop Style/CollectionQuerying
#14288
Conversation
Report
Report
|
214a353
to
f0d2609
Compare
@@ -3660,6 +3660,12 @@ Style/CollectionMethods: | |||
- inject | |||
- reduce | |||
|
|||
Style/CollectionQuerying: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Naming is hard... I named the cop like this because of the cop Style/CollectionMethods
which is also related to Enumerable
, and because in Ruby docs, replacement methods are called Methods for Querying.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting - I wasn't aware of this and it should probably be mentioned somewhere in the docs and the matching style guide rule.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just fyi, I've opened a PR for the style guide: rubocop/ruby-style-guide#962
I love this cop suggestion, but we'll have to polish a few things before we can merge it. Most importantly we should add a matching rule to the style guide (I believe that's non-controversial). I'm also not a fan of the name, so I'll think a bit about some alternatives. |
# matches the argument using `==`, while `any?`, `none?` and `one?` use | ||
# `===`). | ||
# | ||
# @safety |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
any?
/one?
/none?
use thruthiness which results in [nil].any? == false
. That fact has always irked me when using these methods as a replacement for count
comparision. In practise I don't know how big the impact would be, I seem to mostly use the predicates anyways without much issues. But certainly unfortunate.
This should at the very least be mentioned.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah good point! I updated the docs (let me know if I got it right).
Most of the real-world-rails examples seem to be of this form (213 offenses out of 269 total):
Report
./apps/mastodon/app/policies/backup_policy.rb:7:78: C: [Correctable] Style/CollectionQuerying: Use none? instead.
user_signed_in? && current_user.backups.where(created_at: MIN_AGE.ago..).count.zero?
^^^^^^^^^^^
./apps/mastodon/lib/tasks/tests.rake:115:54: C: [Correctable] Style/CollectionQuerying: Use one? instead.
unless Identity.where(provider: 'foo', uid: 0).count == 1
^^^^^^^^^^
./apps/mastodon/lib/tasks/tests.rake:120:68: C: [Correctable] Style/CollectionQuerying: Use one? instead.
unless WebauthnCredential.where(user_id: 1, nickname: 'foo').count == 1
^^^^^^^^^^
./apps/mastodon/lib/tasks/tests.rake:125:89: C: [Correctable] Style/CollectionQuerying: Use one? instead.
unless AccountAlias.where(account_id: 1, uri: 'https://example.com/users/foobar').count == 1
^^^^^^^^^^
./apps/dev.to/app/controllers/stripe_active_cards_controller.rb:57:31: C: [Correctable] Style/CollectionQuerying: Use any? instead.
if customer.subscriptions.count.positive?
^^^^^^^^^^^^^^^
./apps/dev.to/app/models/article.rb:672:35: C: [Correctable] Style/CollectionQuerying: Use any? instead.
return if collection.articles.count.positive?
^^^^^^^^^^^^^^^
./apps/dev.to/app/models/organization.rb:122:30: C: [Correctable] Style/CollectionQuerying: Use one? instead.
organization_memberships.count == 1 && articles.count.zero? && credits.count.zero?
^^^^^^^^^^
./apps/dev.to/app/models/organization.rb:122:53: C: [Correctable] Style/CollectionQuerying: Use none? instead.
organization_memberships.count == 1 && articles.count.zero? && credits.count.zero?
^^^^^^^^^^^
./apps/dev.to/app/models/organization.rb:122:76: C: [Correctable] Style/CollectionQuerying: Use none? instead.
organization_memberships.count == 1 && articles.count.zero? && credits.count.zero?
^^^^^^^^^^^
./apps/dev.to/app/sanitizers/rendered_markdown_scrubber.rb:47:23: C: [Correctable] Style/CollectionQuerying: Use one? instead.
node.attributes.count == 1 &&
^^^^^^^^^^
./apps/dev.to/app/services/moderator/banish_user.rb:55:53: C: [Correctable] Style/CollectionQuerying: Use one? instead.
organization.destroy! if organization.users.count == 1
^^^^^^^^^^
./apps/dev.to/lib/data_update_scripts/20201208151516_set_onboarding_profile_fields_for_existing_forems.rb:4:26: C: [Correctable] Style/CollectionQuerying: Use any? instead.
return unless User.count.positive?
^^^^^^^^^^^^^^^
./apps/discourse/app/controllers/admin/themes_controller.rb:27:26: C: [Correctable] Style/CollectionQuerying: Use any? instead.
if upload.errors.count > 0
^^^^^^^^^
./apps/discourse/app/controllers/admin/watched_words_controller.rb:41:43: C: [Correctable] Style/CollectionQuerying: Use one? instead.
if watched_word_group&.watched_words&.count == 1
^^^^^^^^^^
./apps/discourse/app/controllers/admin/web_hooks_controller.rb:153:59: C: [Correctable] Style/CollectionQuerying: Use none? instead.
raise Discourse::InvalidParameters if web_hook_events.count.zero?
^^^^^^^^^^^
./apps/discourse/app/controllers/invites_controller.rb:583:79: C: [Correctable] Style/CollectionQuerying: Use none? instead.
!SiteSetting.enable_local_logins && Discourse.enabled_auth_providers.count == 0 &&
^^^^^^^^^^
./apps/discourse/app/jobs/onceoff/migrate_censored_words.rb:7:14: C: [Correctable] Style/CollectionQuerying: Use any? instead.
if row.count > 0
^^^^^^^^^
./apps/discourse/app/models/category.rb:1272:10: C: [Correctable] Style/CollectionQuerying: Use any? instead.
tags.count > 0 || tag_groups.count > 0
^^^^^^^^^
./apps/discourse/app/models/category.rb:1272:34: C: [Correctable] Style/CollectionQuerying: Use any? instead.
tags.count > 0 || tag_groups.count > 0
^^^^^^^^^
./apps/discourse/app/models/invite.rb:100:26: C: [Correctable] Style/CollectionQuerying: Use any? instead.
self.invited_users.count > 0
^^^^^^^^^
./apps/discourse/app/models/post.rb:554:11: C: [Correctable] Style/CollectionQuerying: Use any? instead.
flags.count != 0
^^^^^^^^^^
./apps/discourse/app/models/post_analyzer.rb:66:58: C: [Correctable] Style/CollectionQuerying: Use any? instead.
(Post.allowed_image_classes & dom_class.split).count > 0
^^^^^^^^^
./apps/discourse/app/models/quoted_post.rb:74:77: C: [Correctable] Style/CollectionQuerying: Use any? instead.
QuotedPost.where(post_id: post.id, quoted_post_id: reply_post_id).count > 0
^^^^^^^^^
./apps/discourse/app/models/screened_ip_address.rb:104:81: C: [Correctable] Style/CollectionQuerying: Use none? instead.
return false if ScreenedIpAddress.where(action_type: actions[:allow_admin]).count == 0
^^^^^^^^^^
./apps/discourse/app/models/upload.rb:539:18: C: [Correctable] Style/CollectionQuerying: Use none? instead.
if scope.count == 0
^^^^^^^^^^
./apps/discourse/app/services/inline_uploads.rb:26:27: C: [Correctable] Style/CollectionQuerying: Use one? instead.
node.children.count == 1 &&
^^^^^^^^^^
./apps/discourse/app/services/post_alerter.rb:861:77: C: [Correctable] Style/CollectionQuerying: Use one? instead.
return post.topic.first_smtp_enabled_group if post.topic.allowed_groups.count == 1
^^^^^^^^^^
./apps/discourse/app/services/user_destroyer.rb:18:79: C: [Correctable] Style/CollectionQuerying: Use any? instead.
raise PostsExistError if !opts[:delete_posts] && user.posts.joins(:topic).count != 0
^^^^^^^^^^
./apps/discourse/app/services/user_merger.rb:59:21: C: [Correctable] Style/CollectionQuerying: Use none? instead.
return if posts.count == 0
^^^^^^^^^^
./apps/discourse/config/initializers/006-ensure_login_hint.rb:9:46: C: [Correctable] Style/CollectionQuerying: Use none? instead.
User.where(admin: true).human_users.count == 0
^^^^^^^^^^
./apps/discourse/db/migrate/20131022045114_add_uncategorized_category.rb:7:40: C: [Correctable] Style/CollectionQuerying: Use any? instead.
name << SecureRandom.hex if result.count > 0
^^^^^^^^^
./apps/discourse/db/migrate/20170227211458_add_featured_topics_to_categories.rb:11:15: C: [Correctable] Style/CollectionQuerying: Use any? instead.
if result.count > 0 && result[0]["value"].to_i > 0
^^^^^^^^^
./apps/discourse/db/migrate/20170308201552_add_subcategory_list_style_to_categories.rb:15:15: C: [Correctable] Style/CollectionQuerying: Use any? instead.
if result.count > 0
^^^^^^^^^
./apps/discourse/db/migrate/20200409033412_create_bookmarks_from_post_action_bookmarks.rb:35:38: C: [Correctable] Style/CollectionQuerying: Use none? instead.
break if post_action_bookmarks.count.zero?
^^^^^^^^^^^
./apps/discourse/db/migrate/20210224162050_remove_emoji_one_from_emoji_set_site_setting.rb:6:22: C: [Correctable] Style/CollectionQuerying: Use none? instead.
return if result.count.zero?
^^^^^^^^^^^
./apps/discourse/lib/discourse_tagging.rb:98:33: C: [Correctable] Style/CollectionQuerying: Use none? instead.
(category.tags.count == 0 && category.tag_groups.count == 0)
^^^^^^^^^^
./apps/discourse/lib/discourse_tagging.rb:98:67: C: [Correctable] Style/CollectionQuerying: Use none? instead.
(category.tags.count == 0 && category.tag_groups.count == 0)
^^^^^^^^^^
./apps/discourse/lib/discourse_tagging.rb:426:33: C: [Correctable] Style/CollectionQuerying: Use any? instead.
category ? (category.tags.count > 0 || category.tag_groups.count > 0) : false
^^^^^^^^^
./apps/discourse/lib/discourse_tagging.rb:426:66: C: [Correctable] Style/CollectionQuerying: Use any? instead.
category ? (category.tags.count > 0 || category.tag_groups.count > 0) : false
^^^^^^^^^
./apps/discourse/lib/email/receiver.rb:1654:91: C: [Correctable] Style/CollectionQuerying: Use none? instead.
UserDestroyer.new(Discourse.system_user).destroy(user, quiet: true) if user.posts.count == 0
^^^^^^^^^^
./apps/discourse/lib/file_store/s3_store.rb:424:19: C: [Correctable] Style/CollectionQuerying: Use any? instead.
while files.count > 0
^^^^^^^^^
./apps/discourse/lib/guardian.rb:544:7: C: [Correctable] Style/CollectionQuerying: Use none? instead.
).count == 0
^^^^^^^^^^
./apps/discourse/lib/guardian/post_guardian.rb:404:75: C: [Correctable] Style/CollectionQuerying: Use one? instead.
Category.post_create_allowed(self).where(id: topic.category.id).count == 1
^^^^^^^^^^
./apps/discourse/lib/guardian/topic_guardian.rb:61:80: C: [Correctable] Style/CollectionQuerying: Use one? instead.
(!category || Category.topic_create_allowed(self).where(id: category_id).count == 1)
^^^^^^^^^^
./apps/discourse/lib/post_action_creator.rb:298:44: C: [Correctable] Style/CollectionQuerying: Use none? instead.
if post_action && post_action.errors.count == 0
^^^^^^^^^^
./apps/discourse/lib/post_creator.rb:440:41: C: [Correctable] Style/CollectionQuerying: Use none? instead.
return unless @post && @post.errors.count == 0 && @topic && @topic.category_id
^^^^^^^^^^
./apps/discourse/lib/tasks/posts.rake:552:33: C: [Correctable] Style/CollectionQuerying: Use any? instead.
if missing[:post_uploads].count > 0
^^^^^^^^^
./apps/discourse/lib/tasks/site_settings.rake:86:20: C: [Correctable] Style/CollectionQuerying: Use any? instead.
if dead_settings.count > 0
^^^^^^^^^
./apps/discourse/lib/tasks/uploads.rake:962:10: C: [Correctable] Style/CollectionQuerying: Use any? instead.
if all.count > 0
^^^^^^^^^
./apps/discourse/lib/upload_recovery.rb:23:70: C: [Correctable] Style/CollectionQuerying: Use any? instead.
next if (Post.allowed_image_classes & dom_class.split).count > 0
^^^^^^^^^
./apps/discourse/plugins/automation/lib/discourse_automation/scriptable.rb:157:24: C: [Correctable] Style/CollectionQuerying: Use any? instead.
if report.data.count > 0
^^^^^^^^^
./apps/discourse/plugins/chat/app/models/chat/channel_archive.rb:15:88: C: [Correctable] Style/CollectionQuerying: Use none? instead.
self.archived_messages >= self.total_messages && self.chat_channel.chat_messages.count.zero?
^^^^^^^^^^^
./apps/discourse/plugins/chat/db/migrate/20221104054957_backfill_channel_slugs.rb:11:24: C: [Correctable] Style/CollectionQuerying: Use none? instead.
return if channels.count.zero?
^^^^^^^^^^^
./apps/discourse/script/bulk_import/vbulletin.rb:38:49: C: [Correctable] Style/CollectionQuerying: Use any? instead.
@has_post_thanks = mysql_query(<<-SQL).to_a.count > 0
^^^^^^^^^
./apps/discourse/script/import_scripts/lithium.rb:136:27: C: [Correctable] Style/CollectionQuerying: Use any? instead.
location = result.count > 0 ? result.first["nvalue"] : nil
^^^^^^^^^
./apps/discourse/script/import_scripts/lithium.rb:226:48: C: [Correctable] Style/CollectionQuerying: Use any? instead.
elsif attr[:profile].present? && profile.count > 0
^^^^^^^^^
./apps/discourse/script/import_scripts/lithium.rb:228:57: C: [Correctable] Style/CollectionQuerying: Use any? instead.
fields[name] = result.first["nvalue"] if result.count > 0
^^^^^^^^^
./apps/discourse/script/import_scripts/lithium.rb:372:14: C: [Correctable] Style/CollectionQuerying: Use any? instead.
if roles.count > 0
^^^^^^^^^
./apps/discourse/script/import_scripts/lithium.rb:444:27: C: [Correctable] Style/CollectionQuerying: Use any? instead.
if result.count > 0
^^^^^^^^^
./apps/discourse/script/import_scripts/muut.rb:116:60: C: [Correctable] Style/CollectionQuerying: Use any? instead.
if thread["replies"].present? && thread["replies"].count > 0
^^^^^^^^^
./apps/discourse/script/import_scripts/vanilla.rb:148:31: C: [Correctable] Style/CollectionQuerying: Use any? instead.
if first_level_categories.count > 0
^^^^^^^^^
./apps/discourse/script/import_scripts/vanilla.rb:154:34: C: [Correctable] Style/CollectionQuerying: Use any? instead.
if second_level_categories.count > 0
^^^^^^^^^
./apps/discourse/script/import_scripts/vbulletin.rb:192:53: C: [Correctable] Style/CollectionQuerying: Use any? instead.
next if GroupUser.where(group_id: group.id).count > 0
^^^^^^^^^
./apps/discourse/spec/integrity/coding_style_spec.rb:13:9: C: [Correctable] Style/CollectionQuerying: Use any? instead.
lines.count > 0 ? file : nil
^^^^^^^^^
./apps/discourse/spec/system/login_spec.rb:14:58: C: [Correctable] Style/CollectionQuerying: Use any? instead.
wait_for(timeout: 5) { ActionMailer::Base.deliveries.count != 0 }
^^^^^^^^^^
./apps/gitlabhq/app/controllers/concerns/check_initial_setup.rb:11:39: C: [Correctable] Style/CollectionQuerying: Use one? instead.
return false unless User.limit(2).count == 1 # Count as much 2 to know if we have exactly one
^^^^^^^^^^
./apps/gitlabhq/app/controllers/concerns/onboarding/status.rb:14:15: C: [Correctable] Style/CollectionQuerying: Use one? instead.
members.count == 1
^^^^^^^^^^
./apps/gitlabhq/app/controllers/projects/environments_controller.rb:123:47: C: [Correctable] Style/CollectionQuerying: Use one? instead.
job = stop_actions.first if stop_actions&.count == 1
^^^^^^^^^^
./apps/gitlabhq/app/finders/deployments_finder.rb:163:49: C: [Correctable] Style/CollectionQuerying: Use one? instead.
params[:status].present? && params[:status].count == 1 && params[:status].first.to_s == 'success'
^^^^^^^^^^
./apps/gitlabhq/app/models/ci/runner.rb:388:23: C: [Correctable] Style/CollectionQuerying: Use one? instead.
runner_projects.count == 1
^^^^^^^^^^
./apps/gitlabhq/app/models/fork_network_member.rb:20:63: C: [Correctable] Style/CollectionQuerying: Use none? instead.
fork_network.destroy if fork_network.fork_network_members.count == 0
^^^^^^^^^^
./apps/gitlabhq/app/models/integration.rb:644:15: C: [Correctable] Style/CollectionQuerying: Use one? instead.
if events.count == 1
^^^^^^^^^^
./apps/gitlabhq/app/models/milestone.rb:199:30: C: [Correctable] Style/CollectionQuerying: Use none? instead.
active? && issues.opened.count == 0
^^^^^^^^^^
./apps/gitlabhq/app/models/network/graph.rb:259:47: C: [Correctable] Style/CollectionQuerying: Use none? instead.
return leaves if commit.parents(@map).count == 0
^^^^^^^^^^
./apps/gitlabhq/app/models/user.rb:1035:34: C: [Correctable] Style/CollectionQuerying: Use one? instead.
User.non_internal.limit(2).count == 1
^^^^^^^^^^
./apps/gitlabhq/app/presenters/project_presenter.rb:413:33: C: [Correctable] Style/CollectionQuerying: Use one? instead.
cluster_link = clusters.count == 1 ? project_cluster_path(project, clusters.first) : project_clusters_path(project)
^^^^^^^^^^
./apps/gitlabhq/app/services/ci/runners/set_runner_associated_projects_service.rb:53:59: C: [Correctable] Style/CollectionQuerying: Use one? instead.
return error_responses.first if error_responses.count == 1
^^^^^^^^^^
./apps/gitlabhq/app/services/merge_requests/build_service.rb:272:19: C: [Correctable] Style/CollectionQuerying: Use one? instead.
if commits&.count == 1
^^^^^^^^^^
./apps/gitlabhq/app/services/projects/auto_devops/disable_service.rb:26:48: C: [Correctable] Style/CollectionQuerying: Use none? instead.
auto_devops_pipelines.success.limit(1).count == 0 &&
^^^^^^^^^^
./apps/gitlabhq/gems/gitlab-housekeeper/lib/gitlab/housekeeper/keeps/rubocop_fixer.rb:64:35: C: [Correctable] Style/CollectionQuerying: Use one? instead.
next unless data.keys.count == 1
^^^^^^^^^^
./apps/gitlabhq/keeps/overdue_finalize_background_migration.rb:187:28: C: [Correctable] Style/CollectionQuerying: Use one? instead.
return unless result.count == 1
^^^^^^^^^^
./apps/gitlabhq/lib/api/ci/runners.rb:366:129: C: [Correctable] Style/CollectionQuerying: Use one? instead.
forbidden!("Only one project associated with the runner. Please remove the runner instead") if runner.runner_projects.count == 1
^^^^^^^^^^
./apps/gitlabhq/lib/gitlab/ci/config/yaml/documents.rb:39:36: C: [Correctable] Style/CollectionQuerying: Use none? instead.
return {} if documents.count == 0
^^^^^^^^^^
./apps/gitlabhq/lib/gitlab/gitaly_client/analysis_service.rb:45:35: C: [Correctable] Style/CollectionQuerying: Use none? instead.
return [] if request_enum.count == 0
^^^^^^^^^^
./apps/gitlabhq/lib/gitlab/legacy_github_import/importer.rb:195:36: C: [Correctable] Style/CollectionQuerying: Use any? instead.
return unless raw[:labels].count > 0
^^^^^^^^^
./apps/gitlabhq/lib/gitlab/middleware/multipart.rb:48:76: C: [Correctable] Style/CollectionQuerying: Use one? instead.
raise "unexpected field: #{field.inspect}" unless parsed_field.count == 1
^^^^^^^^^^
./apps/gitlabhq/lib/gitlab/middleware/multipart.rb:71:53: C: [Correctable] Style/CollectionQuerying: Use one? instead.
unless hash_path.is_a?(Hash) && hash_path.count == 1
^^^^^^^^^^
./apps/gitlabhq/lib/gitlab/quick_actions/issue_actions.rb:58:48: C: [Correctable] Style/CollectionQuerying: Use one? instead.
quick_action_target.project.boards.count == 1
^^^^^^^^^^
./apps/gitlabhq/lib/gitlab/sidekiq_config.rb:127:64: C: [Correctable] Style/CollectionQuerying: Use one? instead.
.select { |workers| workers.map(&:get_weight).uniq.count == 1 }
^^^^^^^^^^
./apps/gitlabhq/lib/gitlab/usage/metrics/instrumentations/redis_hll_metric.rb:43:45: C: [Correctable] Style/CollectionQuerying: Use one? instead.
return uniques.first if uniques.count == 1
^^^^^^^^^^
./apps/gitlabhq/lib/gitlab/usage_data_counters/quick_action_activity_unique_counter.rb:67:19: C: [Correctable] Style/CollectionQuerying: Use one? instead.
if args.count == 1 && args.first == 'me'
^^^^^^^^^^
./apps/gitlabhq/lib/gitlab/usage_data_counters/quick_action_activity_unique_counter.rb:107:19: C: [Correctable] Style/CollectionQuerying: Use one? instead.
if args.count == 1
^^^^^^^^^^
./apps/gitlabhq/qa/qa/support/page_error_checker.rb:40:36: C: [Correctable] Style/CollectionQuerying: Use one? instead.
"There #{severe_errors.count == 1 ? 'was' : 'were'} #{severe_errors.count} "\
^^^^^^^^^^
./apps/gitlabhq/qa/qa/support/page_error_checker.rb:41:50: C: [Correctable] Style/CollectionQuerying: Use one? instead.
"SEVERE level error#{severe_errors.count == 1 ? '' : 's'}:\n\n#{error_report_for(severe_errors)}"
^^^^^^^^^^
./apps/gitlabhq/scripts/feature_flags/used-feature-flags:95:21: C: [Correctable] Style/CollectionQuerying: Use any? instead.
if additional_flags.count > 0
^^^^^^^^^
./apps/gitlabhq/scripts/feature_flags/used-feature-flags:108:17: C: [Correctable] Style/CollectionQuerying: Use any? instead.
if unused_flags.count > 0
^^^^^^^^^
./apps/gitlabhq/spec/db/schema_spec.rb:431:37: C: [Correctable] Style/CollectionQuerying: Use one? instead.
next if primary_key_columns.count == 1
^^^^^^^^^^
./apps/gitlabhq/spec/lib/gitlab/usage_data_counters/code_review_events_spec.rb:27:27: C: [Correctable] Style/CollectionQuerying: Use one? instead.
definition.events.count == 1
^^^^^^^^^^
./apps/gitlabhq/spec/services/projects/container_repository/third_party/cleanup_tags_service_spec.rb:323:33: C: [Correctable] Style/CollectionQuerying: Use none? instead.
return if selected_tags.count.zero?
^^^^^^^^^^^
./apps/gitlabhq/spec/support/helpers/sharding_key_spec_helpers.rb:16:12: C: [Correctable] Style/CollectionQuerying: Use any? instead.
result.count > 0
^^^^^^^^^
./apps/gitlabhq/spec/support/helpers/sharding_key_spec_helpers.rb:37:12: C: [Correctable] Style/CollectionQuerying: Use any? instead.
result.count > 0
^^^^^^^^^
./apps/gitlabhq/spec/support/helpers/sharding_key_spec_helpers.rb:57:12: C: [Correctable] Style/CollectionQuerying: Use any? instead.
result.count > 0
^^^^^^^^^
./apps/gitlabhq/spec/support/helpers/sharding_key_spec_helpers.rb:90:12: C: [Correctable] Style/CollectionQuerying: Use any? instead.
result.count > 0
^^^^^^^^^
./apps/gitlabhq/spec/support/matchers/query_matcher.rb:11:16: C: [Correctable] Style/CollectionQuerying: Use any? instead.
@counter.count > 0
^^^^^^^^^
./apps/gitlabhq/spec/support/shared_examples/quick_actions/issuable/issuable_quick_actions_shared_examples.rb:55:33: C: [Correctable] Style/CollectionQuerying: Use one? instead.
expect(noteable.todos.count == 1).to eq(can_use_quick_action)
^^^^^^^^^^
./apps/openproject/app/controllers/admin_controller.rb:50:20: C: [Correctable] Style/CollectionQuerying: Use one? instead.
if @menu_nodes.count == 1
^^^^^^^^^^
./apps/openproject/app/helpers/user_consent_helper.rb:58:29: C: [Correctable] Style/CollectionQuerying: Use none? instead.
if Setting.consent_info.count == 0
^^^^^^^^^^
./apps/openproject/app/models/custom_option.rb:48:67: C: [Correctable] Style/CollectionQuerying: Use any? instead.
return if CustomOption.where(custom_field_id:).where.not(id:).count > 0
^^^^^^^^^
./apps/openproject/app/models/journable/historic_active_record_relation.rb:300:31: C: [Correctable] Style/CollectionQuerying: Use none? instead.
if relation.select_values.count == 0
^^^^^^^^^^
./apps/openproject/app/models/journable/historic_active_record_relation.rb:302:34: C: [Correctable] Style/CollectionQuerying: Use one? instead.
elsif relation.select_values.count == 1 and
^^^^^^^^^^
./apps/openproject/app/models/work_package.rb:200:84: C: [Correctable] Style/CollectionQuerying: Use any? instead.
TimeEntry.on_work_packages(work_packages).count > 0
^^^^^^^^^
./apps/openproject/app/models/work_packages/costs.rb:42:104: C: [Correctable] Style/CollectionQuerying: Use any? instead.
->(work_packages) { CostEntry.on_work_packages(work_packages).count.positive? },
^^^^^^^^^^^^^^^
./apps/openproject/app/seeders/demo_data/group_seeder.rb:39:13: C: [Correctable] Style/CollectionQuerying: Use none? instead.
Group.count.zero?
^^^^^^^^^^^
./apps/openproject/app/seeders/demo_data/overview_seeder.rb:28:23: C: [Correctable] Style/CollectionQuerying: Use none? instead.
Grids::Overview.count.zero? && demo_projects_exist?
^^^^^^^^^^^
./apps/openproject/app/seeders/demo_data/projects_seeder.rb:47:15: C: [Correctable] Style/CollectionQuerying: Use none? instead.
Project.count.zero?
^^^^^^^^^^^
./apps/openproject/app/seeders/development_data/custom_fields_seeder.rb:102:48: C: [Correctable] Style/CollectionQuerying: Use none? instead.
CustomField.where("name LIKE 'CF DEV%'").count == 0
^^^^^^^^^^
./apps/openproject/app/seeders/development_data/projects_seeder.rb:50:78: C: [Correctable] Style/CollectionQuerying: Use none? instead.
recent_installation? && Project.where(identifier: project_identifiers).count == 0
^^^^^^^^^^
./apps/openproject/app/services/ldap/base_service.rb:107:18: C: [Correctable] Style/CollectionQuerying: Use none? instead.
if entries.count == 0
^^^^^^^^^^
./apps/openproject/db/migrate/20190920102446_clean_custom_values.rb:37:19: C: [Correctable] Style/CollectionQuerying: Use any? instead.
if invalid_cv.count > 0
^^^^^^^^^
./apps/openproject/lib/api/errors/multiple_errors.rb:37:39: C: [Correctable] Style/CollectionQuerying: Use one? instead.
return errors.first if errors.count == 1
^^^^^^^^^^
./apps/openproject/lib/open_project/scm/adapters/git.rb:102:54: C: [Correctable] Style/CollectionQuerying: Use any? instead.
raise Exceptions::SCMEmpty unless branches.count > 0
^^^^^^^^^
./apps/openproject/lib/tasks/attachment_migrations.rake:67:20: C: [Correctable] Style/CollectionQuerying: Use any? instead.
if Journal.count > 0
^^^^^^^^^
./apps/openproject/modules/bim/db/migrate/20201105154216_seed_custom_style_with_bim_theme.rb:44:25: C: [Correctable] Style/CollectionQuerying: Use none? instead.
(DesignColor.count == 0 &&
^^^^^^^^^^
./apps/openproject/modules/bim/db/migrate/20210521080035_update_xkt_to_version8.rb:47:17: C: [Correctable] Style/CollectionQuerying: Use none? instead.
if IfcModel.count.zero?
^^^^^^^^^^^
./apps/openproject/modules/meeting/app/controllers/concerns/meetings/agenda_component_streams.rb:205:56: C: [Correctable] Style/CollectionQuerying: Use one? instead.
elsif meeting_agenda_item.meeting.agenda_items.count == 1
^^^^^^^^^^
./apps/openproject/modules/meeting/app/controllers/concerns/meetings/agenda_component_streams.rb:281:41: C: [Correctable] Style/CollectionQuerying: Use one? instead.
if current_section.agenda_items.count == 1
^^^^^^^^^^
./apps/openproject/modules/reporting/app/controllers/cost_reports_controller.rb:340:24: C: [Correctable] Style/CollectionQuerying: Use any? instead.
t.cost_entries.count > 0
^^^^^^^^^
./apps/openproject/modules/reporting/lib/widget/filters/operators.rb:33:58: C: [Correctable] Style/CollectionQuerying: Use one? instead.
hide_select_box = filter_class.available_operators.count == 1 || filter_class.heavy?
^^^^^^^^^^
./apps/openproject/modules/storages/app/common/storages/peripherals/storage_interaction/nextcloud/files_query.rb:132:25: C: [Correctable] Style/CollectionQuerying: Use none? instead.
return [] if path.count == 0
^^^^^^^^^^
./apps/openproject/spec/support/components/wysiwyg/wysiwyg_editor.rb:83:19: C: [Correctable] Style/CollectionQuerying: Use any? instead.
if images.count > 0
^^^^^^^^^
./apps/openproject/spec/support/rspec_cleanup.rb:21:21: C: [Correctable] Style/CollectionQuerying: Use none? instead.
next if cls.count == 0
^^^^^^^^^^
./apps/canvas-lms/app/controllers/assignments_controller.rb:77:56: C: [Correctable] Style/CollectionQuerying: Use any? instead.
HAS_ASSIGNMENTS: @context.active_assignments.count > 0,
^^^^^^^^^
./apps/canvas-lms/app/controllers/calendar_events_api_controller.rb:839:78: C: [Correctable] Style/CollectionQuerying: Use none? instead.
if @event.appointment_group && @event.appointment_group.appointments.count == 0
^^^^^^^^^^
./apps/canvas-lms/app/controllers/calendar_events_api_controller.rb:866:79: C: [Correctable] Style/CollectionQuerying: Use none? instead.
if event.appointment_group && @event.appointment_group.appointments.count == 0
^^^^^^^^^^
./apps/canvas-lms/app/controllers/learner_passport_controller.rb:853:151: C: [Correctable] Style/CollectionQuerying: Use any? instead.
pathway[:learner_groups] = learner_passport_learner_groups.select { |lg| pathway[:learner_groups].include?(lg[:id]) } if pathway[:learner_groups].count > 0
^^^^^^^^^
./apps/canvas-lms/app/controllers/lti/ims/tool_setting_controller.rb:203:34: C: [Correctable] Style/CollectionQuerying: Use one? instead.
valid = json["@graph"].count == 1
^^^^^^^^^^
./apps/canvas-lms/app/controllers/provisional_grades_controller.rb:259:85: C: [Correctable] Style/CollectionQuerying: Use one? instead.
selected_provisional_grade = provisional_grades.first if provisional_grades.count == 1
^^^^^^^^^^
./apps/canvas-lms/app/controllers/quizzes/quizzes_controller.rb:1028:126: C: [Correctable] Style/CollectionQuerying: Use any? instead.
@any_submissions_pending_review = submitted_with_submissions.where("quiz_submissions.workflow_state = 'pending_review'").count > 0
^^^^^^^^^
./apps/canvas-lms/app/controllers/rubrics_api_controller.rb:404:27: C: [Correctable] Style/CollectionQuerying: Use one? instead.
elsif inclusion_items.count == 1
^^^^^^^^^^
./apps/canvas-lms/app/controllers/wiki_pages_api_controller.rb:595:81: C: [Correctable] Style/CollectionQuerying: Use any? instead.
render json: { conflict: @context.wiki.wiki_pages.not_deleted.where(title:).count > 0 }
^^^^^^^^^
./apps/canvas-lms/app/graphql/mutations/base_learning_outcome_mutation.rb:46:38: C: [Correctable] Style/CollectionQuerying: Use any? instead.
return {} unless ratings_input.count.positive? && context
^^^^^^^^^^^^^^^
./apps/canvas-lms/app/graphql/types/user_type.rb:293:80: C: [Correctable] Style/CollectionQuerying: Use any? instead.
contexts_collection = contexts_collection[0][1] if contexts_collection.count > 0
^^^^^^^^^
./apps/canvas-lms/app/graphql/types/user_type.rb:294:71: C: [Correctable] Style/CollectionQuerying: Use any? instead.
users_collection = users_collection[0][1] if users_collection.count > 0
^^^^^^^^^
./apps/canvas-lms/app/helpers/canvas_outcomes_helper.rb:152:33: C: [Correctable] Style/CollectionQuerying: Use any? instead.
response.first[:alignments].count > 0
^^^^^^^^^
./apps/canvas-lms/app/helpers/canvas_outcomes_helper.rb:173:112: C: [Correctable] Style/CollectionQuerying: Use any? instead.
return true if get_request_page(context, domain, "api/authoritative_results", jwt, params, 1, 1)[:results].count > 0
^^^^^^^^^
./apps/canvas-lms/app/helpers/conversations_helper.rb:171:108: C: [Correctable] Style/CollectionQuerying: Use one? instead.
@recipients.reject! { |u| u.id == current_user.id } unless @recipients == [current_user] && recipients.count == 1
^^^^^^^^^^
./apps/canvas-lms/app/helpers/gradebooks_helper.rb:196:23: C: [Correctable] Style/CollectionQuerying: Use one? instead.
if override_dates.count == 1
^^^^^^^^^^
./apps/canvas-lms/app/models/account.rb:2074:30: C: [Correctable] Style/CollectionQuerying: Use any? instead.
if allowed_service_names.count > 0 && !["+", "-"].include?(allowed_service_names[0][0, 1])
^^^^^^^^^
./apps/canvas-lms/app/models/account.rb:2109:32: C: [Correctable] Style/CollectionQuerying: Use any? instead.
if allowed_service_names.count > 0
^^^^^^^^^
./apps/canvas-lms/app/models/account_notification.rb:60:21: C: [Correctable] Style/CollectionQuerying: Use any? instead.
return if roles.count > 0 && (roles & ["StudentEnrollment", "ObserverEnrollment"]).none?
^^^^^^^^^
./apps/canvas-lms/app/models/appointment_group.rb:149:56: C: [Correctable] Style/CollectionQuerying: Use none? instead.
if (@new_sub_context_codes & context_subs).count == 0
^^^^^^^^^^
./apps/canvas-lms/app/models/attachment.rb:1736:95: C: [Correctable] Style/CollectionQuerying: Use any? instead.
while SubmissionDraftAttachment.where(attachment_id: attachments).limit(1000).destroy_all.count > 0 do end
^^^^^^^^^
./apps/canvas-lms/app/models/content_export.rb:617:46: C: [Correctable] Style/CollectionQuerying: Use any? instead.
context.assignments.active.type_quiz_lti.count.positive?
^^^^^^^^^^^^^^^
./apps/canvas-lms/app/models/content_migration.rb:829:156: C: [Correctable] Style/CollectionQuerying: Use any? instead.
return true if outcome.learning_outcome_results.where("workflow_state <> 'deleted' AND context_type='Course' AND context_code='course_#{context.id}'").count > 0
^^^^^^^^^
./apps/canvas-lms/app/models/context_module.rb:693:50: C: [Correctable] Style/CollectionQuerying: Use any? instead.
if content_tags.not_deleted.where(position:).count != 0
^^^^^^^^^^
./apps/canvas-lms/app/models/course.rb:3933:37: C: [Correctable] Style/CollectionQuerying: Use none? instead.
if student_view_students.active.count == 0
^^^^^^^^^^
./apps/canvas-lms/app/models/courses/export_warnings.rb:30:113: C: [Correctable] Style/CollectionQuerying: Use any? instead.
if assignments.active.joins(:grading_standard).where.not(grading_standards: { workflow_state: "active" }).count > 0
^^^^^^^^^
./apps/canvas-lms/app/models/discussion_entry.rb:245:36: C: [Correctable] Style/CollectionQuerying: Use none? instead.
if discussion_entry_versions.count == 0 && !message_old.nil?
^^^^^^^^^^
./apps/canvas-lms/app/models/discussion_topic.rb:179:25: C: [Correctable] Style/CollectionQuerying: Use any? instead.
if unlocked_teacher.count > 0
^^^^^^^^^
./apps/canvas-lms/app/models/group_membership.rb:114:40: C: [Correctable] Style/CollectionQuerying: Use one? instead.
record.group.group_memberships.count == 1 &&
^^^^^^^^^^
./apps/canvas-lms/app/models/importers/learning_outcome_importer.rb:39:110: C: [Correctable] Style/CollectionQuerying: Use any? instead.
next if LearningOutcome.active.where(id: o.fetch_outcome_copies, context_id: migration.context_id).count > 0
^^^^^^^^^
./apps/canvas-lms/app/models/notification.rb:704:32: C: [Correctable] Style/CollectionQuerying: Use any? instead.
user.teacher_enrollments.count > 0 || user.ta_enrollments.count > 0
^^^^^^^^^
./apps/canvas-lms/app/models/notification.rb:704:65: C: [Correctable] Style/CollectionQuerying: Use any? instead.
user.teacher_enrollments.count > 0 || user.ta_enrollments.count > 0
^^^^^^^^^
./apps/canvas-lms/app/models/quizzes/quiz_regrade_run.rb:49:89: C: [Correctable] Style/CollectionQuerying: Use one? instead.
!!(new && old.nil?) && Quizzes::QuizRegradeRun.where(quiz_regrade_id: quiz_regrade).count == 1
^^^^^^^^^^
./apps/canvas-lms/app/models/rubric_association.rb:175:52: C: [Correctable] Style/CollectionQuerying: Use none? instead.
rubric.destroy if rubric.rubric_associations.count == 0 && rubric.rubric_assessments.count == 0
^^^^^^^^^^
./apps/canvas-lms/app/models/rubric_association.rb:175:92: C: [Correctable] Style/CollectionQuerying: Use none? instead.
rubric.destroy if rubric.rubric_associations.count == 0 && rubric.rubric_assessments.count == 0
^^^^^^^^^^
./apps/canvas-lms/app/models/rubric_association.rb:240:64: C: [Correctable] Style/CollectionQuerying: Use none? instead.
rubric.destroy if cnt == 0 && rubric.rubric_associations.count == 0 && !rubric.public
^^^^^^^^^^
./apps/canvas-lms/app/models/speed_grader/assignment.rb:453:24: C: [Correctable] Style/CollectionQuerying: Use none? instead.
unless pgs.count == 0 || (pgs.count == 1 && pgs.first.scorer_id == current_user.id)
^^^^^^^^^^
./apps/canvas-lms/app/models/speed_grader/assignment.rb:453:43: C: [Correctable] Style/CollectionQuerying: Use one? instead.
unless pgs.count == 0 || (pgs.count == 1 && pgs.first.scorer_id == current_user.id)
^^^^^^^^^^
./apps/canvas-lms/app/models/user_learning_object_scopes.rb:390:81: C: [Correctable] Style/CollectionQuerying: Use none? instead.
as.lazy.reject { |a| Assignments::NeedsGradingCountQuery.new(a, self).count == 0 }.take(limit).to_a
^^^^^^^^^^
./apps/canvas-lms/app/presenters/mark_done_presenter.rb:46:32: C: [Correctable] Style/CollectionQuerying: Use one? instead.
item_ids.first if item_ids.count == 1
^^^^^^^^^^
./apps/canvas-lms/build/new-jenkins/crystalball_merge_coverage.rb:37:37: C: [Correctable] Style/CollectionQuerying: Use none? instead.
if spec.empty? || changed_files.count.zero?
^^^^^^^^^^^
./apps/canvas-lms/doc/yard_plugins/lti_variable_expansion_plugin.rb:36:68: C: [Correctable] Style/CollectionQuerying: Use any? instead.
deprecated_str = " *[deprecated]*" if object.tags(:deprecated).count > 0
^^^^^^^^^
./apps/canvas-lms/doc/yard_plugins/lti_variable_expansion_plugin.rb:39:28: C: [Correctable] Style/CollectionQuerying: Use any? instead.
example = example_tags.count > 0 && example_tags.first
^^^^^^^^^
./apps/canvas-lms/doc/yard_plugins/lti_variable_expansion_plugin.rb:51:34: C: [Correctable] Style/CollectionQuerying: Use any? instead.
duplicates = duplicates_tags.count > 0 && duplicates_tags.first
^^^^^^^^^
./apps/canvas-lms/gems/plugins/qti_exporter/lib/qti/assessment_test_converter.rb:188:25: C: [Correctable] Style/CollectionQuerying: Use one? instead.
elsif bank_refs.count == 1
^^^^^^^^^^
./apps/canvas-lms/gems/plugins/qti_exporter/lib/qti/calculated_interaction.rb:130:32: C: [Correctable] Style/CollectionQuerying: Use one? instead.
if @question[:variables].count == 1
^^^^^^^^^^
./apps/canvas-lms/lib/api/v1/context_module.rb:62:28: C: [Correctable] Style/CollectionQuerying: Use none? instead.
return nil if tags.count == 0
^^^^^^^^^^
./apps/canvas-lms/lib/brand_account_chain_resolver.rb:60:16: C: [Correctable] Style/CollectionQuerying: Use one? instead.
if actives.count == 1
^^^^^^^^^^
./apps/canvas-lms/lib/brand_account_chain_resolver.rb:69:60: C: [Correctable] Style/CollectionQuerying: Use one? instead.
break unless next_children.present? && next_children.count == 1
^^^^^^^^^^
./apps/canvas-lms/lib/canvas/live_events.rb:986:66: C: [Correctable] Style/CollectionQuerying: Use any? instead.
aligned_to_outcomes: rubric_assessment.aligned_outcome_ids.count.positive?,
^^^^^^^^^^^^^^^
./apps/canvas-lms/lib/canvas/migration/archive.rb:51:59: C: [Correctable] Style/CollectionQuerying: Use one? instead.
@nested_dir = root_dirs.first.name if root_dirs.count == 1
^^^^^^^^^^
./apps/canvas-lms/lib/canvas/migration/helpers/selective_content_formatter.rb:130:64: C: [Correctable] Style/CollectionQuerying: Use any? instead.
next unless course_data[type2] && course_data[type2].count > 0
^^^^^^^^^
./apps/canvas-lms/lib/cc/assignment_groups.rb:23:58: C: [Correctable] Style/CollectionQuerying: Use any? instead.
return nil unless @course.assignment_groups.active.count > 0
^^^^^^^^^
./apps/canvas-lms/lib/cc/basic_lti_links.rb:23:63: C: [Correctable] Style/CollectionQuerying: Use any? instead.
return nil unless @course.context_external_tools.active.count > 0
^^^^^^^^^
./apps/canvas-lms/lib/cc/events.rb:24:46: C: [Correctable] Style/CollectionQuerying: Use any? instead.
return nil unless calendar_event_scope.count > 0
^^^^^^^^^
./apps/canvas-lms/lib/cc/exporter/web_zip/zip_package.rb:281:45: C: [Correctable] Style/CollectionQuerying: Use any? instead.
:all if modul.completion_requirements.count > 0
^^^^^^^^^
./apps/canvas-lms/lib/cc/external_feeds.rb:23:48: C: [Correctable] Style/CollectionQuerying: Use any? instead.
return nil unless @course.external_feeds.count > 0
^^^^^^^^^
./apps/canvas-lms/lib/cc/module_meta.rb:23:61: C: [Correctable] Style/CollectionQuerying: Use any? instead.
return nil unless @course.context_modules.not_deleted.count > 0
^^^^^^^^^
./apps/canvas-lms/lib/cc/qti/qti_items.rb:405:70: C: [Correctable] Style/CollectionQuerying: Use any? instead.
return nil unless question["answers"] && question["answers"].count > 0
^^^^^^^^^
./apps/canvas-lms/lib/cc/rubrics.rb:23:53: C: [Correctable] Style/CollectionQuerying: Use any? instead.
return nil unless @course.rubric_associations.count > 0
^^^^^^^^^
./apps/canvas-lms/lib/data_fixup/populate_root_account_id_on_models.rb:547:12: C: [Correctable] Style/CollectionQuerying: Use one? instead.
(names.count == 1) ? names.first : "COALESCE(#{names.join(", ")})"
^^^^^^^^^^
./apps/canvas-lms/lib/data_fixup/populate_root_account_ids_on_learning_outcomes.rb:30:32: C: [Correctable] Style/CollectionQuerying: Use one? instead.
if Account.root_accounts.count == 1
^^^^^^^^^^
./apps/canvas-lms/lib/data_fixup/rebuild_quiz_submissions_from_quiz_submission_events.rb:189:28: C: [Correctable] Style/CollectionQuerying: Use any? instead.
if seen_question_ids.count > 0
^^^^^^^^^
./apps/canvas-lms/lib/dates_overridable.rb:247:20: C: [Correctable] Style/CollectionQuerying: Use any? instead.
if overrides.count > 0 && overrides.count == context.active_section_count
^^^^^^^^^
./apps/canvas-lms/lib/lti/variable_expander.rb:2036:34: C: [Correctable] Style/CollectionQuerying: Use one? instead.
if val&.count == 1 && (course_id = val.first["course_id"])
^^^^^^^^^^
./apps/canvas-lms/lib/messageable_user/calculator.rb:466:61: C: [Correctable] Style/CollectionQuerying: Use any? instead.
if section_or_id.respond_to?(:count) && section_or_id.count > 0
^^^^^^^^^
./apps/canvas-lms/lib/user_list_v2.rb:131:18: C: [Correctable] Style/CollectionQuerying: Use one? instead.
if results.count == 1
^^^^^^^^^^
./apps/canvas-lms/lib/user_list_v2.rb:133:67: C: [Correctable] Style/CollectionQuerying: Use one? instead.
elsif results.uniq { |r| Shard.global_id_for(r[:user_id]) }.count == 1
^^^^^^^^^^
./apps/canvas-lms/spec/initializers/periodic_jobs_spec.rb:33:27: C: [Correctable] Style/CollectionQuerying: Use any? instead.
expect(Delayed::Job.count > 0).to be(true)
^^^^^^^^^
./apps/canvas-lms/spec/initializers/periodic_jobs_spec.rb:40:27: C: [Correctable] Style/CollectionQuerying: Use any? instead.
expect(Delayed::Job.count > 0).to be(true)
^^^^^^^^^
./apps/canvas-lms/spec/initializers/periodic_jobs_spec.rb:47:27: C: [Correctable] Style/CollectionQuerying: Use any? instead.
expect(Delayed::Job.count > 0).to be(true)
^^^^^^^^^
./apps/canvas-lms/spec/lib/canvas/live_events_spec.rb:3046:71: C: [Correctable] Style/CollectionQuerying: Use any? instead.
aligned_to_outcomes: @rubric_assessment.aligned_outcome_ids.count.positive?,
^^^^^^^^^^^^^^^
./apps/canvas-lms/spec/lib/canvas/live_events_spec.rb:3071:71: C: [Correctable] Style/CollectionQuerying: Use any? instead.
aligned_to_outcomes: @rubric_assessment.aligned_outcome_ids.count.positive?,
^^^^^^^^^^^^^^^
./apps/canvas-lms/spec/models/account_notification_spec.rb:457:54: C: [Correctable] Style/CollectionQuerying: Use none? instead.
if u.enrollments.active_or_pending_by_date.count == 0 && u.user_account_associations.count > 0
^^^^^^^^^^
./apps/canvas-lms/spec/models/account_notification_spec.rb:457:96: C: [Correctable] Style/CollectionQuerying: Use any? instead.
if u.enrollments.active_or_pending_by_date.count == 0 && u.user_account_associations.count > 0
^^^^^^^^^
./apps/canvas-lms/spec/requests/pace_contexts_spec.rb:116:56: C: [Correctable] Style/CollectionQuerying: Use any? instead.
expected_pace_type = (section.course_paces.count > 0) ? "Section" : "Course"
^^^^^^^^^
./apps/canvas-lms/spec/selenium/admin/admin_sub_accounts_spec.rb:32:27: C: [Correctable] Style/CollectionQuerying: Use one? instead.
(created_sub_accounts.count == 1) ? created_sub_accounts[0] : created_sub_accounts
^^^^^^^^^^
./apps/canvas-lms/spec/selenium/dashboard/dashboard_teacher_spec.rb:295:32: C: [Correctable] Style/CollectionQuerying: Use one? instead.
until all_todo_links.count == 1 || num_attempts == max_attempts
^^^^^^^^^^
./apps/canvas-lms/spec/selenium/master_courses/blueprint_associations_spec.rb:47:27: C: [Correctable] Style/CollectionQuerying: Use one? instead.
(created_sub_accounts.count == 1) ? created_sub_accounts[0] : created_sub_accounts
^^^^^^^^^^
./apps/canvas-lms/spec/selenium/outcomes/account_admin_state_outcomes_spec.rb:157:70: C: [Correctable] Style/CollectionQuerying: Use one? instead.
wait_for(method: nil, timeout: 2) { find_outcome_modal_items.count == 1 }
^^^^^^^^^^
./apps/canvas-lms/spec/selenium/shared_components/copy_to_tray_page.rb:112:59: C: [Correctable] Style/CollectionQuerying: Use one? instead.
wait_for(method: nil, timeout: 1) { dropdowns_in_tray.count == 1 }
^^^^^^^^^^
./apps/canvas-lms/spec/support/crystalball.rb:231:37: C: [Correctable] Style/CollectionQuerying: Use any? instead.
elsif file_changes["new"].count.positive?
^^^^^^^^^^^^^^^
49358 files inspected, 213 offenses detected, 213 offenses autocorrectable
I haven't thought about this scenario to be honest. I see that there's a fair number of #count
called on ActiveRecord relations (makes sense considering which codebases have been investigated) or ActiveModel::Errors
, neither of which have falsy values, but yeah generally speaking this could break some code if not careful.
f0d2609
to
4297e81
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This pull request adds a new cop, Style/CollectionQuerying, that enforces the use of predicate methods (such as any?, none?, one?, and many?) over equivalent expressions using Enumerable#count. Key changes include the implementation of the new cop in lib/rubocop/cop/style/collection_querying.rb, comprehensive tests in spec/rubocop/cop/style/collection_querying_spec.rb, and updates to related formatter and cop files to use the more concise one?/any? patterns.
Reviewed Changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated no comments.
Show a summary per file
File | Description |
---|---|
spec/rubocop/cop/style/collection_querying_spec.rb | Added tests validating offenses and autocorrections for count usage |
lib/rubocop/formatter/offense_count_formatter.rb | Updated file phrase logic to use one? instead of count |
lib/rubocop/formatter/fuubar_style_formatter.rb | Similar update for file phrase logic |
lib/rubocop/cop/style/symbol_proc.rb | Refined argument count checking by using any? |
lib/rubocop/cop/style/redundant_interpolation.rb | Changed count check from count.zero? style to use any? |
lib/rubocop/cop/style/hash_conversion.rb | Replaced arguments.count with one? |
lib/rubocop/cop/style/collection_querying.rb | Implements the new cop with mappings from count expressions to predicates |
lib/rubocop/cop/style/case_like_if.rb | Replaced count.positive? with any? |
lib/rubocop/cop/lint/redundant_regexp_quantifiers.rb | Changed count with block to one? for clarity in quantifier logic |
lib/rubocop/cop/layout/closing_parenthesis_indentation.rb | Replaced .uniq.count == 1 with .uniq.one? for clarity |
lib/rubocop.rb | Added require of the new cop file |
config/default.yml | Added configuration for the new cop |
changelog/new_cop_style_collection_querying.md | Changelog entry for the new cop |
.rubocop.yml | Added the new cop to the InternalAffairs module list |
Comments suppressed due to low confidence (1)
spec/rubocop/cop/style/collection_querying_spec.rb:64
- [nitpick] The block parameter 'it' may be confused with common RSpec DSL usage. Consider renaming it to a more explicit parameter (e.g., 'item') to improve clarity in test examples.
x.count { it.foo? }.positive?
Before we merge this:
Might be a good idea to add some aggressive mode that actually checks for them as well - would be useful for one-off refactoring runs I guess. |
4297e81
to
8e35b47
Compare
Done 👍
I agree, I ran the cop on real-world-rails and made it check just for real-world-rails report
|
Yeah, I'm fine with a follow-up PR. This one is good to go as far as I'm concerned. Thanks! |
Hey folks - just trying out the new rubocop release in a (non-Rails) project, and finding this cop is reporting false positives. i.e. objects that respond to I'm not sure about presuming anything that responds to It's been a while since I looked into Rubocop internals - I'm presuming there's no way to reliably detect that the |
I'm also seeing some issues after upgrading. In a Rails application that uses Mongoid, it is changing Is this something I should create an issue for, or is it not likely to be fixed? I guess Rubocop is a static analyzer, so without checking what the class is, you'll have no way to know if Edit: This also has performance implications in Mongoid. It changed |
That's right, RuboCop is a static analyzer, so it can't actually know whether your receiver includes Enumerable.
Uhh that's unfortunate. I was thinking of following up on this PR with some additional configurations:
With these two config options, I think you'll be able to reliably reduce the number of false positives. Probably not eliminate, but that's the case for any cop. @bbatsov what do you think about the new config options? |
Adds new cop to identify places where expressions with
Enumerable#count
can be replaced with an appropriate predicate method.The cop will register code such as:
as offenses, and autocorrect it to:
It does not register e.g.
x.count(foo)
as an offense becausecount
and predicate methods function differently in that form (this has been documented in more detail in cop docs). It also doesn't register that form because it would yield false positives, e.g. forString#count
(and that's not the case for forms without arguments, or with a block).It recognizes the following combinations:
Target Ruby and Rails versions
any?
,none?
andone?
have been implemented onEnumerable
since at least v2.3.many?
is registered as an offense only whenActiveSupportExtensionsEnabled
config option is enabled since this method comes from Active Support.Enumerable#many?
has been implemented in AS in its present form since v2.2.0.Performance aspect
There's also a performance aspect to this cop, for example,
x.count(&:foo?).positive?
will iterate over every element in collection, whilex.any?(&:foo?)
will stop as soon as the first element returns a truthy value for#foo?
:Benchmark (block)
Benchmark (no arguments)
Impact
I believe this cop will have a wide impact; this GH search shows at least 122k results (8 offenses have been caught in this codebase alone). Additionally I ran the cop on some known public projects (mastodon, dev.to, discourse, gitlabhq, openproject, canvas-lms) with the help of real-world-rails, and it caught 269 offenses (report in next comment).
Before submitting the PR make sure the following are checked:
[Fix #issue-number]
(if the related issue exists).master
(if not - rebase it).bundle exec rake default
. It executes all tests and runs RuboCop on its own code.{change_type}_{change_description}.md
if the new code introduces user-observable changes. See changelog entry format for details.