From f9cc3dc4b7717d6dc40369742ef7cec1f918949a Mon Sep 17 00:00:00 2001 From: David Taylor Date: Mon, 2 Mar 2020 19:22:49 +0000 Subject: [PATCH] PERF: Allow passing an existing list of user field ids when loading (#8970) * PERF: Allow passing an existing list of user field ids when loading This avoids the need for running `UserField.pluck(:id)` for each user that is serialized * Memoize user_fields to avoid rebuilding hash ever time --- app/models/user.rb | 22 +++++++++++++--------- app/serializers/user_card_serializer.rb | 4 ++-- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/app/models/user.rb b/app/models/user.rb index c4aa017b8da..e8cc35f891c 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -475,7 +475,7 @@ class User < ActiveRecord::Base @unread_notifications = nil @unread_total_notifications = nil @unread_pms = nil - @user_fields = nil + @user_fields_cache = nil @ignored_user_ids = nil @muted_user_ids = nil super @@ -1093,16 +1093,20 @@ class User < ActiveRecord::Base USER_FIELD_PREFIX ||= "user_field_" - def user_fields - return @user_fields if @user_fields - user_field_ids = UserField.pluck(:id) - if user_field_ids.present? - @user_fields = {} - user_field_ids.each do |fid| - @user_fields[fid.to_s] = custom_fields["#{USER_FIELD_PREFIX}#{fid}"] + def user_fields(field_ids = nil) + if field_ids.nil? + field_ids = (@all_user_field_ids ||= UserField.pluck(:id)) + end + + @user_fields_cache ||= {} + + # Memoize based on requested fields + @user_fields_cache[field_ids.join(':')] ||= {}.tap do |hash| + field_ids.each do |fid| + # The hash keys are strings for backwards compatibility + hash[fid.to_s] = custom_fields["#{USER_FIELD_PREFIX}#{fid}"] end end - @user_fields end def number_of_deleted_posts diff --git a/app/serializers/user_card_serializer.rb b/app/serializers/user_card_serializer.rb index a689fc59570..5d53a6258c6 100644 --- a/app/serializers/user_card_serializer.rb +++ b/app/serializers/user_card_serializer.rb @@ -140,8 +140,8 @@ class UserCardSerializer < BasicUserSerializer end def user_fields - allowed_keys = scope.allowed_user_field_ids(object).map(&:to_s) - object.user_fields&.select { |k, v| allowed_keys.include?(k) } + allowed_keys = scope.allowed_user_field_ids(object) + object.user_fields(allowed_keys) end def include_user_fields?