Add a separate finder for collecting children of groups
This commit is contained in:
parent
283e13b836
commit
063b531211
2 changed files with 125 additions and 0 deletions
54
app/finders/group_children_finder.rb
Normal file
54
app/finders/group_children_finder.rb
Normal file
|
@ -0,0 +1,54 @@
|
|||
class GroupChildrenFinder
|
||||
include Gitlab::Allowable
|
||||
|
||||
attr_reader :current_user, :parent_group, :params
|
||||
|
||||
def initialize(current_user = nil, parent_group:, params: {})
|
||||
@current_user = current_user
|
||||
@parent_group = parent_group
|
||||
@params = params
|
||||
end
|
||||
|
||||
def execute
|
||||
Kaminari.paginate_array(children)
|
||||
end
|
||||
|
||||
# This allows us to fetch only the count without loading the objects. Unless
|
||||
# the objects were already loaded.
|
||||
def total_count
|
||||
@total_count ||= if defined?(@children)
|
||||
children.size
|
||||
else
|
||||
child_groups.count + projects.count
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def children
|
||||
@children ||= child_groups + projects
|
||||
end
|
||||
|
||||
def child_groups
|
||||
return Group.none unless Group.supports_nested_groups?
|
||||
return Group.none unless can?(current_user, :read_group, parent_group)
|
||||
|
||||
groups = GroupsFinder.new(current_user,
|
||||
parent: parent_group,
|
||||
all_available: true,
|
||||
all_children_for_parent: params[:filter_groups].present?).execute
|
||||
|
||||
groups = groups.search(params[:filter]) if params[:filter].present?
|
||||
groups = groups.includes(:route).includes(:children)
|
||||
groups.sort(params[:sort])
|
||||
end
|
||||
|
||||
def projects
|
||||
return Project.none unless can?(current_user, :read_group, parent_group)
|
||||
|
||||
projects = GroupProjectsFinder.new(group: parent_group, params: params, current_user: current_user).execute
|
||||
projects = projects.includes(:route)
|
||||
projects = projects.search(params[:filter]) if params[:filter].present?
|
||||
projects.sort(params[:sort])
|
||||
end
|
||||
end
|
71
spec/finders/group_children_finder_spec.rb
Normal file
71
spec/finders/group_children_finder_spec.rb
Normal file
|
@ -0,0 +1,71 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe GroupChildrenFinder do
|
||||
let(:user) { create(:user) }
|
||||
let(:group) { create(:group) }
|
||||
let(:params) { {} }
|
||||
subject(:finder) { described_class.new(user, parent_group: group, params: params) }
|
||||
|
||||
before do
|
||||
group.add_owner(user)
|
||||
end
|
||||
|
||||
describe '#execute' do
|
||||
it 'includes projects' do
|
||||
project = create(:project, namespace: group)
|
||||
|
||||
expect(finder.execute).to contain_exactly(project)
|
||||
end
|
||||
|
||||
context 'with a filter' do
|
||||
let(:params) { { filter: 'test' } }
|
||||
|
||||
it 'includes only projects matching the filter' do
|
||||
_other_project = create(:project, namespace: group)
|
||||
matching_project = create(:project, namespace: group, name: 'testproject')
|
||||
|
||||
expect(finder.execute).to contain_exactly(matching_project)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with nested groups', :nested_groups do
|
||||
let!(:project) { create(:project, namespace: group) }
|
||||
let!(:subgroup) { create(:group, parent: group) }
|
||||
|
||||
describe '#execute' do
|
||||
it 'contains projects and subgroups' do
|
||||
expect(finder.execute).to contain_exactly(subgroup, project)
|
||||
end
|
||||
|
||||
context 'with a filter' do
|
||||
let(:params) { { filter: 'test' } }
|
||||
|
||||
it 'contains only matching projects and subgroups' do
|
||||
matching_project = create(:project, namespace: group, name: 'Testproject')
|
||||
matching_subgroup = create(:group, name: 'testgroup', parent: group)
|
||||
|
||||
expect(finder.execute).to contain_exactly(matching_subgroup, matching_project)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#total_count' do
|
||||
it 'counts the array children were already loaded' do
|
||||
finder.instance_variable_set(:@children, [double])
|
||||
|
||||
expect(finder).not_to receive(:child_groups)
|
||||
expect(finder).not_to receive(:projects)
|
||||
|
||||
expect(finder.total_count).to eq(1)
|
||||
end
|
||||
|
||||
it 'performs a count without loading children when they are not loaded yet' do
|
||||
expect(finder).to receive(:child_groups).and_call_original
|
||||
expect(finder).to receive(:projects).and_call_original
|
||||
|
||||
expect(finder.total_count).to eq(2)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue