Skip to content

Commit 7f13bb1

Browse files
committed
1247: add manual xml_id-uniqueness validations for tests and model_solutions
1 parent 5a9d6d3 commit 7f13bb1

File tree

7 files changed

+45
-21
lines changed

7 files changed

+45
-21
lines changed

app/models/model_solution.rb

+8-5
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,7 @@ class ModelSolution < ApplicationRecord
1212
validates :xml_id, presence: true
1313
validates :parent_id, uniqueness: {scope: :task}, if: -> { parent_id.present? }
1414
validate :parent_validation_check
15-
# TODO: For new tasks, this validation is currently useless, because the validation is performed
16-
# before the task is saved (and thus the task_id is not yet known, i.e., is NULL). Therefore,
17-
# one can create a **new task** with a test that has the same xml_id as another test of the same task.
18-
# TODO: This validation is currently useless on new records, because the uuid is generated after validation
19-
validates :xml_id, uniqueness: {scope: :task_id}
15+
validate :unique_xml_id, if: -> { !task.nil? && xml_id_changed? }
2016

2117
def duplicate(set_parent_id: true)
2218
dup.tap do |model_solution|
@@ -26,4 +22,11 @@ def duplicate(set_parent_id: true)
2622
end
2723
end
2824
end
25+
26+
private
27+
28+
def unique_xml_id
29+
xml_ids = (task.model_solutions - [self]).map(&:xml_id)
30+
errors.add(:xml_id, :not_unique) if xml_ids.include? xml_id
31+
end
2932
end

app/models/test.rb

+8-4
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,7 @@ class Test < ApplicationRecord
1212
validates :xml_id, presence: true
1313
validates :parent_id, uniqueness: {scope: :task}, if: -> { parent_id.present? }
1414
validate :parent_validation_check
15-
# TODO: For new tasks, this validation is currently useless, because the validation is performed
16-
# before the task is saved (and thus the task_id is not yet known, i.e., is NULL). Therefore,
17-
# one can create a **new task** with a test that has the same xml_id as another test of the same task.
18-
validates :xml_id, uniqueness: {scope: :task_id}
15+
validate :unique_xml_id, if: -> { !task.nil? && xml_id_changed? }
1916

2017
def configuration_as_xml
2118
Dachsfisch::JSON2XMLConverter.perform(json: configuration.to_json)
@@ -29,4 +26,11 @@ def duplicate(set_parent_id: true)
2926
end
3027
end
3128
end
29+
30+
private
31+
32+
def unique_xml_id
33+
xml_ids = (task.tests - [self]).map(&:xml_id)
34+
errors.add(:xml_id, :not_unique) if xml_ids.include? xml_id
35+
end
3236
end

config/locales/de/models.yml

+2-4
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,8 @@ de:
101101
omniauth_provider: OmniAuth-Anbieter
102102
provider_uid: Anbieter-UID
103103
errors:
104+
messages:
105+
not_unique: is not unique
104106
models:
105107
collection:
106108
attributes:
@@ -120,10 +122,6 @@ de:
120122
not_iso639: ist kein zweistelliger ISO-639-1- oder dreistelliger ISO-639-2-Sprachcode
121123
task_contribution:
122124
duplicated: wurde bereits erzeugt und wartet auf Genehmigung. Bitte bearbeiten Sie Ihren vorhandenen Änderungsvorschlag, anstatt einen neuen anzulegen.
123-
task_file:
124-
attributes:
125-
xml_id:
126-
not_unique: ist nicht eindeutig
127125
user:
128126
attributes:
129127
avatar:

config/locales/en/models.yml

+2-4
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,8 @@ en:
101101
omniauth_provider: OmniAuth Provider
102102
provider_uid: Provider UID
103103
errors:
104+
messages:
105+
not_unique: is not unique
104106
models:
105107
collection:
106108
attributes:
@@ -120,10 +122,6 @@ en:
120122
not_iso639: is not a two letter ISO 639-1 or three letter ISO-639-2 language code
121123
task_contribution:
122124
duplicated: has been created already and is currently waiting for approval. Please edit your existing contribution instead of creating a new one
123-
task_file:
124-
attributes:
125-
xml_id:
126-
not_unique: is not unique
127125
user:
128126
attributes:
129127
avatar:

spec/models/model_solution_spec.rb

+12-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,18 @@
66
describe 'validations' do
77
it { is_expected.to belong_to(:task) }
88
it { is_expected.to validate_presence_of(:xml_id) }
9-
it { is_expected.to validate_uniqueness_of(:xml_id).scoped_to(:task_id) }
9+
10+
context 'when a task is created with multiple model_solutions' do
11+
before { build(:task, model_solutions: [model_solution, build(:model_solution, xml_id: 'same')]) }
12+
13+
let(:model_solution) { build(:model_solution, xml_id: 'same') }
14+
15+
it 'validates xml_id correctly' do
16+
model_solution.validate
17+
expect(model_solution.errors.full_messages).to include "#{described_class.human_attribute_name('xml_id')} #{I18n.t('activerecord.errors.messages.not_unique')}"
18+
end
19+
end
20+
1021

1122
it_behaves_like 'parent validation with parent_id', :model_solution
1223
end

spec/models/task_file_spec.rb

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
it 'has correct error' do
2020
file.validate
21-
expect(file.errors.full_messages).to include "#{described_class.human_attribute_name('xml_id')} #{I18n.t('activerecord.errors.models.task_file.attributes.xml_id.not_unique')}"
21+
expect(file.errors.full_messages).to include "#{described_class.human_attribute_name('xml_id')} #{I18n.t('activerecord.errors.messages.not_unique')}"
2222
end
2323
end
2424

@@ -96,7 +96,7 @@
9696

9797
it 'has correct error' do
9898
file.validate
99-
expect(file.errors.full_messages).to include "#{described_class.human_attribute_name('xml_id')} #{I18n.t('activerecord.errors.models.task_file.attributes.xml_id.not_unique')}"
99+
expect(file.errors.full_messages).to include "#{described_class.human_attribute_name('xml_id')} #{I18n.t('activerecord.errors.messages.not_unique')}"
100100
end
101101
end
102102

spec/models/test_spec.rb

+11-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,17 @@
77
it { is_expected.to belong_to(:task) }
88
it { is_expected.to validate_presence_of(:title) }
99
it { is_expected.to validate_presence_of(:xml_id) }
10-
it { is_expected.to validate_uniqueness_of(:xml_id).scoped_to(:task_id) }
10+
11+
context 'when a task is created with multiple tests' do
12+
before { build(:task, tests: [test, build(:test, xml_id: 'same')]) }
13+
14+
let(:test) { build(:test, xml_id: 'same') }
15+
16+
it 'validates xml_id correctly' do
17+
test.validate
18+
expect(test.errors.full_messages).to include "#{described_class.human_attribute_name('xml_id')} #{I18n.t('activerecord.errors.messages.not_unique')}"
19+
end
20+
end
1121

1222
it_behaves_like 'parent validation with parent_id', :test
1323
end

0 commit comments

Comments
 (0)