Skip to content

Commit

Permalink
Merge pull request #13385 from opf/bug/49569-selected-values-are-mult…
Browse files Browse the repository at this point in the history
…iplied-on-cf-multi-select

[#49569] Selected values are multiplied on CF multi-select
  • Loading branch information
dombesz authored Aug 7, 2023
2 parents 93075de + 8c77564 commit 7e5d963
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 7 deletions.
9 changes: 6 additions & 3 deletions app/models/work_package.rb
Original file line number Diff line number Diff line change
Expand Up @@ -460,14 +460,16 @@ def self.available_custom_fields(work_package)

def self.preload_available_custom_fields(work_packages)
custom_fields = available_custom_fields_from_db(work_packages)
.select('projects.id project_id',
'types.id type_id',
.select('array_agg(projects.id) available_project_ids',
'array_agg(types.id) available_type_ids',
'custom_fields.*')
.group('custom_fields.id')

work_packages.each do |work_package|
RequestStore.store[available_custom_field_key(work_package)] = custom_fields
.select do |cf|
((cf.project_id == work_package.project_id) || cf.is_for_all?) && cf.type_id == work_package.type_id
(cf.available_project_ids.include?(work_package.project_id) || cf.is_for_all?) &&
cf.available_type_ids.include?(work_package.type_id)
end
end
end
Expand All @@ -482,6 +484,7 @@ def self.available_custom_fields_from_db(work_packages)
.references(:projects, :types)
.where(is_for_all: true)
.where(types: { id: work_packages.map(&:type_id).uniq }))
.distinct
end
private_class_method :available_custom_fields_from_db

Expand Down
35 changes: 31 additions & 4 deletions spec/models/work_package/work_package_acts_as_customizable_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,14 @@ def setup_custom_field(cf)
type:)
end

let(:project2) { create(:project) }
let(:type2) { create(:type) }
let(:work_package2) do
build(:work_package,
project: project2,
type: type2)
end

let!(:custom_field_of_project_and_type) do
create(:work_package_custom_field,
name: 'Custom field of type and project').tap do |cf|
Expand Down Expand Up @@ -202,23 +210,41 @@ def setup_custom_field(cf)
is_for_all: true)
end

let!(:custom_field_of_projects_and_types_for_all) do
create(:work_package_custom_field,
name: 'Custom field for all and many types and projects',
is_for_all: true).tap do |cf|
project.work_package_custom_fields << cf
type.custom_fields << cf
project2.work_package_custom_fields << cf
type2.custom_fields << cf
end
end

context 'when preloading the custom fields' do
before do
described_class.preload_available_custom_fields([work_package])
described_class.preload_available_custom_fields([work_package, work_package2])
# Bad replacement to check that no database query is run.
allow(WorkPackageCustomField)
.to receive(:left_joins)
.and_call_original
end

it 'returns all custom fields of the project and type' do
it 'returns all custom fields of the project and type for work_package' do
expect(work_package.available_custom_fields)
.to contain_exactly(custom_field_of_project_and_type,
custom_field_for_all_and_type)
custom_field_for_all_and_type,
custom_field_of_projects_and_types_for_all)
end

it 'returns all custom fields of the project and type for work_package2' do
expect(work_package2.available_custom_fields)
.to contain_exactly(custom_field_of_projects_and_types_for_all)
end

it 'does not call the database' do
work_package.available_custom_fields
work_package2.available_custom_fields

expect(WorkPackageCustomField)
.not_to have_received(:left_joins)
Expand All @@ -229,7 +255,8 @@ def setup_custom_field(cf)
it 'returns all custom fields of the project and type' do
expect(work_package.available_custom_fields)
.to contain_exactly(custom_field_of_project_and_type,
custom_field_for_all_and_type)
custom_field_for_all_and_type,
custom_field_of_projects_and_types_for_all)
end
end
end
Expand Down

0 comments on commit 7e5d963

Please sign in to comment.