Memoize a user's personal projects count

The method User#projects_limit_left would run "personal_projects.count"
but such a query is not memoized. As a result multiple calls to
User#projects_limit_left would result in multiple COUNT(*) queries being
executed.

To work around this this commit adds User#personal_projects_count which
simply memoizes the result of the COUNT(*) in an instance variable.
This commit is contained in:
Yorick Peterse 2017-08-04 16:43:01 +02:00
parent 4a915c739d
commit ab738645a7
No known key found for this signature in database
GPG Key ID: EDD30D2BEB691AC9
3 changed files with 33 additions and 1 deletions

View File

@ -632,7 +632,11 @@ class User < ActiveRecord::Base
end
def projects_limit_left
projects_limit - personal_projects.count
projects_limit - personal_projects_count
end
def personal_projects_count
@personal_projects_count ||= personal_projects.count
end
def projects_limit_percent

View File

@ -0,0 +1,4 @@
---
title: Memoize the number of personal projects a user has to reduce COUNT queries
merge_request:
author:

View File

@ -1976,4 +1976,28 @@ describe User do
expect(user.allow_password_authentication?).to be_falsey
end
end
describe '#personal_projects_count' do
it 'returns the number of personal projects using a single query' do
user = build(:user)
projects = double(:projects, count: 1)
expect(user).to receive(:personal_projects).once.and_return(projects)
2.times do
expect(user.personal_projects_count).to eq(1)
end
end
end
describe '#projects_limit_left' do
it 'returns the number of projects that can be created by the user' do
user = build(:user)
allow(user).to receive(:projects_limit).and_return(10)
allow(user).to receive(:personal_projects_count).and_return(5)
expect(user.projects_limit_left).to eq(5)
end
end
end