From 087ed84367537ac168ed3e00bb7eb4bd582dc3d0 Mon Sep 17 00:00:00 2001 From: luigi <007.lva@gmail.com> Date: Sat, 9 Jan 2021 18:32:01 -0500 Subject: [PATCH] Optimize map { ... }.compact calls (#15513) * Optimize map { ... }.compact using Enumerable#filter_map, supported since Ruby 2.7 * Add poyfill for Enumerable#filter_map --- .../api/v1/crypto/keys/claims_controller.rb | 2 +- .../api/v1/crypto/keys/queries_controller.rb | 2 +- app/controllers/concerns/cache_concern.rb | 2 +- app/lib/activitypub/activity/flag.rb | 4 +-- app/lib/entity_cache.rb | 2 +- app/lib/spam_check.rb | 4 +-- app/models/account.rb | 4 +-- .../concerns/status_threading_concern.rb | 2 +- app/models/custom_filter.rb | 2 +- app/models/notification.rb | 2 +- app/models/status.rb | 4 +-- .../status_relationships_presenter.rb | 2 +- .../fetch_featured_collection_service.rb | 3 +-- .../activitypub/process_collection_service.rb | 2 +- .../activitypub/process_poll_service.rb | 2 +- .../synchronize_followers_service.rb | 2 +- app/services/fetch_link_card_service.rb | 2 +- app/services/import_service.rb | 4 +-- app/validators/existing_username_validator.rb | 2 +- config/application.rb | 1 + lib/enumerable.rb | 26 +++++++++++++++++++ lib/paperclip/attachment_extensions.rb | 2 +- 22 files changed, 52 insertions(+), 26 deletions(-) create mode 100644 lib/enumerable.rb diff --git a/app/controllers/api/v1/crypto/keys/claims_controller.rb b/app/controllers/api/v1/crypto/keys/claims_controller.rb index 34b21a3809..f9d202d67b 100644 --- a/app/controllers/api/v1/crypto/keys/claims_controller.rb +++ b/app/controllers/api/v1/crypto/keys/claims_controller.rb @@ -12,7 +12,7 @@ class Api::V1::Crypto::Keys::ClaimsController < Api::BaseController private def set_claim_results - @claim_results = devices.map { |device_params| ::Keys::ClaimService.new.call(current_account, device_params[:account_id], device_params[:device_id]) }.compact + @claim_results = devices.filter_map { |device_params| ::Keys::ClaimService.new.call(current_account, device_params[:account_id], device_params[:device_id]) } end def resource_params diff --git a/app/controllers/api/v1/crypto/keys/queries_controller.rb b/app/controllers/api/v1/crypto/keys/queries_controller.rb index 0851d797d3..e6ce9f9192 100644 --- a/app/controllers/api/v1/crypto/keys/queries_controller.rb +++ b/app/controllers/api/v1/crypto/keys/queries_controller.rb @@ -17,7 +17,7 @@ class Api::V1::Crypto::Keys::QueriesController < Api::BaseController end def set_query_results - @query_results = @accounts.map { |account| ::Keys::QueryService.new.call(account) }.compact + @query_results = @accounts.filter_map { |account| ::Keys::QueryService.new.call(account) } end def account_ids diff --git a/app/controllers/concerns/cache_concern.rb b/app/controllers/concerns/cache_concern.rb index abbdb410a5..8d82eda5c1 100644 --- a/app/controllers/concerns/cache_concern.rb +++ b/app/controllers/concerns/cache_concern.rb @@ -45,7 +45,7 @@ module CacheConcern end end - raw.map { |item| cached_keys_with_value[item.id] || uncached[item.id] }.compact + raw.filter_map { |item| cached_keys_with_value[item.id] || uncached[item.id] } end def cache_collection_paginated_by_id(raw, klass, limit, options) diff --git a/app/lib/activitypub/activity/flag.rb b/app/lib/activitypub/activity/flag.rb index 1659bc61fe..8dfc76f0a6 100644 --- a/app/lib/activitypub/activity/flag.rb +++ b/app/lib/activitypub/activity/flag.rb @@ -4,8 +4,8 @@ class ActivityPub::Activity::Flag < ActivityPub::Activity def perform return if skip_reports? - target_accounts = object_uris.map { |uri| account_from_uri(uri) }.compact.select(&:local?) - target_statuses_by_account = object_uris.map { |uri| status_from_uri(uri) }.compact.select(&:local?).group_by(&:account_id) + target_accounts = object_uris.filter_map { |uri| account_from_uri(uri) }.select(&:local?) + target_statuses_by_account = object_uris.filter_map { |uri| status_from_uri(uri) }.select(&:local?).group_by(&:account_id) target_accounts.each do |target_account| target_statuses = target_statuses_by_account[target_account.id] diff --git a/app/lib/entity_cache.rb b/app/lib/entity_cache.rb index 89cbf8d2c4..e38a3adcdc 100644 --- a/app/lib/entity_cache.rb +++ b/app/lib/entity_cache.rb @@ -29,7 +29,7 @@ class EntityCache uncached.each_value { |item| Rails.cache.write(to_key(:emoji, item.shortcode, domain), item, expires_in: MAX_EXPIRATION) } end - shortcodes.map { |shortcode| cached[to_key(:emoji, shortcode, domain)] || uncached[shortcode] }.compact + shortcodes.filter_map { |shortcode| cached[to_key(:emoji, shortcode, domain)] || uncached[shortcode] } end def to_key(type, *ids) diff --git a/app/lib/spam_check.rb b/app/lib/spam_check.rb index 652d036150..68e586d00b 100644 --- a/app/lib/spam_check.rb +++ b/app/lib/spam_check.rb @@ -186,9 +186,9 @@ class SpamCheck def matching_status_ids if nilsimsa? - other_digests.select { |record| record.start_with?('nilsimsa') && nilsimsa_compare_value(digest, record.split(':')[1]) >= NILSIMSA_COMPARE_THRESHOLD }.map { |record| record.split(':')[2] }.compact + other_digests.select { |record| record.start_with?('nilsimsa') && nilsimsa_compare_value(digest, record.split(':')[1]) >= NILSIMSA_COMPARE_THRESHOLD }.filter_map { |record| record.split(':')[2] } else - other_digests.select { |record| record.start_with?('md5') && record.split(':')[1] == digest }.map { |record| record.split(':')[2] }.compact + other_digests.select { |record| record.start_with?('md5') && record.split(':')[1] == digest }.filter_map { |record| record.split(':')[2] } end end diff --git a/app/models/account.rb b/app/models/account.rb index 1f723e2064..75ebfb2f33 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -508,7 +508,7 @@ class Account < ApplicationRecord def from_text(text) return [] if text.blank? - text.scan(MENTION_RE).map { |match| match.first.split('@', 2) }.uniq.map do |(username, domain)| + text.scan(MENTION_RE).map { |match| match.first.split('@', 2) }.uniq.filter_map do |(username, domain)| domain = begin if TagManager.instance.local_domain?(domain) nil @@ -517,7 +517,7 @@ class Account < ApplicationRecord end end EntityCache.instance.mention(username, domain) - end.compact + end end private diff --git a/app/models/concerns/status_threading_concern.rb b/app/models/concerns/status_threading_concern.rb index a0ead1995a..5c04108e4c 100644 --- a/app/models/concerns/status_threading_concern.rb +++ b/app/models/concerns/status_threading_concern.rb @@ -83,7 +83,7 @@ module StatusThreadingConcern def find_statuses_from_tree_path(ids, account, promote: false) statuses = Status.with_accounts(ids).to_a account_ids = statuses.map(&:account_id).uniq - domains = statuses.map(&:account_domain).compact.uniq + domains = statuses.filter_map(&:account_domain).uniq relations = relations_map_for_account(account, account_ids, domains) statuses.reject! { |status| StatusFilter.new(status, account, relations).filtered? } diff --git a/app/models/custom_filter.rb b/app/models/custom_filter.rb index 8df8a4fbf3..9d0f3729b3 100644 --- a/app/models/custom_filter.rb +++ b/app/models/custom_filter.rb @@ -46,7 +46,7 @@ class CustomFilter < ApplicationRecord private def clean_up_contexts - self.context = Array(context).map(&:strip).map(&:presence).compact + self.context = Array(context).map(&:strip).filter_map(&:presence) end def remove_cache diff --git a/app/models/notification.rb b/app/models/notification.rb index e83123c973..b6db37d6dc 100644 --- a/app/models/notification.rb +++ b/app/models/notification.rb @@ -92,7 +92,7 @@ class Notification < ApplicationRecord end def reload_stale_associations!(cached_items) - account_ids = (cached_items.map(&:from_account_id) + cached_items.map { |item| item.target_status&.account_id }.compact).uniq + account_ids = (cached_items.map(&:from_account_id) + cached_items.filter_map { |item| item.target_status&.account_id }).uniq return if account_ids.empty? diff --git a/app/models/status.rb b/app/models/status.rb index b426f9d5bc..558a37f99a 100644 --- a/app/models/status.rb +++ b/app/models/status.rb @@ -334,7 +334,7 @@ class Status < ApplicationRecord def from_text(text) return [] if text.blank? - text.scan(FetchLinkCardService::URL_PATTERN).map(&:first).uniq.map do |url| + text.scan(FetchLinkCardService::URL_PATTERN).map(&:first).uniq.filter_map do |url| status = begin if TagManager.instance.local_url?(url) ActivityPub::TagManager.instance.uri_to_resource(url, Status) @@ -343,7 +343,7 @@ class Status < ApplicationRecord end end status&.distributable? ? status : nil - end.compact + end end end diff --git a/app/presenters/status_relationships_presenter.rb b/app/presenters/status_relationships_presenter.rb index 3cc905a75e..f4849d245b 100644 --- a/app/presenters/status_relationships_presenter.rb +++ b/app/presenters/status_relationships_presenter.rb @@ -14,7 +14,7 @@ class StatusRelationshipsPresenter else statuses = statuses.compact status_ids = statuses.flat_map { |s| [s.id, s.reblog_of_id] }.uniq.compact - conversation_ids = statuses.map(&:conversation_id).compact.uniq + conversation_ids = statuses.filter_map(&:conversation_id).uniq pinnable_status_ids = statuses.map(&:proper).select { |s| s.account_id == current_account_id && %w(public unlisted).include?(s.visibility) }.map(&:id) @reblogs_map = Status.reblogs_map(status_ids, current_account_id).merge(options[:reblogs_map] || {}) diff --git a/app/services/activitypub/fetch_featured_collection_service.rb b/app/services/activitypub/fetch_featured_collection_service.rb index 2c27704661..82c861f5b8 100644 --- a/app/services/activitypub/fetch_featured_collection_service.rb +++ b/app/services/activitypub/fetch_featured_collection_service.rb @@ -24,8 +24,7 @@ class ActivityPub::FetchFeaturedCollectionService < BaseService def process_items(items) status_ids = items.map { |item| value_or_id(item) } .reject { |uri| ActivityPub::TagManager.instance.local_uri?(uri) } - .map { |uri| ActivityPub::FetchRemoteStatusService.new.call(uri) } - .compact + .filter_map { |uri| ActivityPub::FetchRemoteStatusService.new.call(uri) } .select { |status| status.account_id == @account.id } .map(&:id) diff --git a/app/services/activitypub/process_collection_service.rb b/app/services/activitypub/process_collection_service.rb index f1d175dacc..170e6709cd 100644 --- a/app/services/activitypub/process_collection_service.rb +++ b/app/services/activitypub/process_collection_service.rb @@ -37,7 +37,7 @@ class ActivityPub::ProcessCollectionService < BaseService end def process_items(items) - items.reverse_each.map { |item| process_item(item) }.compact + items.reverse_each.filter_map { |item| process_item(item) } end def supported_context? diff --git a/app/services/activitypub/process_poll_service.rb b/app/services/activitypub/process_poll_service.rb index 903b6a78ad..d83e614d88 100644 --- a/app/services/activitypub/process_poll_service.rb +++ b/app/services/activitypub/process_poll_service.rb @@ -30,7 +30,7 @@ class ActivityPub::ProcessPollService < BaseService voters_count = @json['votersCount'] - latest_options = items.map { |item| item['name'].presence || item['content'] }.compact + latest_options = items.filter_map { |item| item['name'].presence || item['content'] } # If for some reasons the options were changed, it invalidates all previous # votes, so we need to remove them diff --git a/app/services/activitypub/synchronize_followers_service.rb b/app/services/activitypub/synchronize_followers_service.rb index d83fcf55e6..93cd602533 100644 --- a/app/services/activitypub/synchronize_followers_service.rb +++ b/app/services/activitypub/synchronize_followers_service.rb @@ -14,7 +14,7 @@ class ActivityPub::SynchronizeFollowersService < BaseService # should never happen in practice, since in almost all cases we keep an # Account record, and should we not do that, we should have sent a Delete. # In any case there is not much we can do if that occurs. - @expected_followers = items.map { |uri| ActivityPub::TagManager.instance.uri_to_resource(uri, Account) }.compact + @expected_followers = items.filter_map { |uri| ActivityPub::TagManager.instance.uri_to_resource(uri, Account) } remove_unexpected_local_followers! handle_unexpected_outgoing_follows! diff --git a/app/services/fetch_link_card_service.rb b/app/services/fetch_link_card_service.rb index 7efa310547..255490d5cd 100644 --- a/app/services/fetch_link_card_service.rb +++ b/app/services/fetch_link_card_service.rb @@ -67,7 +67,7 @@ class FetchLinkCardService < BaseService else html = Nokogiri::HTML(@status.text) links = html.css('a') - urls = links.map { |a| Addressable::URI.parse(a['href']) unless skip_link?(a) }.compact.map(&:normalize).compact + urls = links.filter_map { |a| Addressable::URI.parse(a['href']) unless skip_link?(a) }.filter_map(&:normalize) end urls.reject { |uri| bad_url?(uri) }.first diff --git a/app/services/import_service.rb b/app/services/import_service.rb index 0c6ef2238e..b115322831 100644 --- a/app/services/import_service.rb +++ b/app/services/import_service.rb @@ -107,12 +107,12 @@ class ImportService < BaseService end end - statuses = items.map do |uri| + statuses = items.filter_map do |uri| status = ActivityPub::TagManager.instance.uri_to_resource(uri, Status) next if status.nil? && ActivityPub::TagManager.instance.local_uri?(uri) status || ActivityPub::FetchRemoteStatusService.new.call(uri) - end.compact + end account_ids = statuses.map(&:account_id) preloaded_relations = relations_map_for_account(@account, account_ids) diff --git a/app/validators/existing_username_validator.rb b/app/validators/existing_username_validator.rb index b31d098273..723302ec9b 100644 --- a/app/validators/existing_username_validator.rb +++ b/app/validators/existing_username_validator.rb @@ -5,7 +5,7 @@ class ExistingUsernameValidator < ActiveModel::EachValidator return if value.blank? if options[:multiple] - missing_usernames = value.split(',').map { |username| username.strip.gsub(/\A@/, '') }.map { |username| username unless Account.find_local(username) }.compact + missing_usernames = value.split(',').map { |username| username.strip.gsub(/\A@/, '') }.filter_map { |username| username unless Account.find_local(username) } record.errors.add(attribute, I18n.t('existing_username_validator.not_found_multiple', usernames: missing_usernames.join(', '))) if missing_usernames.any? else record.errors.add(attribute, I18n.t('existing_username_validator.not_found')) unless Account.find_local(value.strip.gsub(/\A@/, '')) diff --git a/config/application.rb b/config/application.rb index af77352212..696dc17e66 100644 --- a/config/application.rb +++ b/config/application.rb @@ -7,6 +7,7 @@ require 'rails/all' Bundler.require(*Rails.groups) require_relative '../app/lib/exceptions' +require_relative '../lib/enumerable' require_relative '../lib/redis/namespace_extensions' require_relative '../lib/paperclip/url_generator_extensions' require_relative '../lib/paperclip/attachment_extensions' diff --git a/lib/enumerable.rb b/lib/enumerable.rb new file mode 100644 index 0000000000..66918f65e8 --- /dev/null +++ b/lib/enumerable.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +module Enumerable + # TODO: Remove this once stop to support Ruby 2.6 + if RUBY_VERSION < '2.7.0' + def filter_map + if block_given? + result = [] + each do |element| + res = yield element + result << res if res + end + result + else + Enumerator.new do |yielder| + result = [] + each do |element| + res = yielder.yield element + result << res if res + end + result + end + end + end + end +end diff --git a/lib/paperclip/attachment_extensions.rb b/lib/paperclip/attachment_extensions.rb index 94f7769b65..e25a34213b 100644 --- a/lib/paperclip/attachment_extensions.rb +++ b/lib/paperclip/attachment_extensions.rb @@ -27,7 +27,7 @@ module Paperclip return true if original_filename == other_filename return false if original_filename.nil? - formats = styles.values.map(&:format).compact + formats = styles.values.filter_map(&:format) return false if formats.empty?