diff options
Diffstat (limited to 'lib/api/entities/issuable_entity.rb')
-rw-r--r-- | lib/api/entities/issuable_entity.rb | 36 |
1 files changed, 32 insertions, 4 deletions
diff --git a/lib/api/entities/issuable_entity.rb b/lib/api/entities/issuable_entity.rb index 5bee59de539..e2c674c0b8b 100644 --- a/lib/api/entities/issuable_entity.rb +++ b/lib/api/entities/issuable_entity.rb @@ -8,10 +8,38 @@ module API expose :title, :description expose :state, :created_at, :updated_at - # Avoids an N+1 query when metadata is included - def issuable_metadata(subject, options, method, args = nil) - cached_subject = options.dig(:issuable_metadata, subject.id) - (cached_subject || subject).public_send(method, *args) # rubocop: disable GitlabSecurity/PublicSend + def presented + lazy_issuable_metadata + + super + end + + def issuable_metadata + options.dig(:issuable_metadata, object.id) || lazy_issuable_metadata + end + + protected + + # This method will preload the `issuable_metadata` for the current + # entity according to the current top-level entity options, such + # as the current_user. + def lazy_issuable_metadata + BatchLoader.for(object).batch(key: [current_user, :issuable_metadata]) do |models, loader, args| + current_user = args[:key].first + + issuable_metadata = Gitlab::IssuableMetadata.new(current_user, models) + metadata_by_id = issuable_metadata.data + + models.each do |issuable| + loader.call(issuable, metadata_by_id[issuable.id]) + end + end + end + + private + + def current_user + options[:current_user] end end end |