Feature/69034 change enforcement of project attributes on creation for templates#21055
Conversation
6f1ac74 to
6525755
Compare
6525755 to
3c9d201
Compare
EinLama
left a comment
There was a problem hiding this comment.
It works, well done 🚀
I am wondering about the state that we carry around in acts_as_customizable, see my comment there. And I have an issue with one spec that is missing a useful expectation. Otherwise, this looks great.
| Projects::Settings::NameForm.new(f), | ||
| Projects::Settings::RelationsForm.new(f), | ||
| Projects::Settings::CustomFieldsForm.new(f) | ||
| *(Projects::Settings::CustomFieldsForm.new(f) unless template) |
There was a problem hiding this comment.
TIL about this use case of the splat operator. I longed for something like this many times, but didn't know about it. That's great!
| else | ||
| custom_field_values | ||
| end | ||
| @custom_values_to_validate ||= persisted? ? [] : custom_field_values |
There was a problem hiding this comment.
This is a subtle change in logic. Now, a record that is validated multiple times will only consider custom values that were there for the first validation - since these are cached.
Also, as soon as the AttributeService calls #deactivate_custom_field_validations!, that deactivation change is permanent until the record is reloaded.
For the use cases that I can think of, this assumption works and will cause no problems. But if it leads to bug, that one would be hard to find 😅 That being said, I could not provoke this to happen in the wizard.
There was a problem hiding this comment.
Yes, that is an interesting point, that could happen for example, if custom values are changed between 2 validation calls on the object. We also cache the Edit: True but not relevant.available_custom_fields array, so that variable is also susceptible for this issue. I think it's safe to assume with the current codebase it's not going to cause a problem.
Edit2: A potential solution would be to store the custom fields to be validated, instead of the custom values. Then in the validate_custom_values method, always validate the fresh list of custom values.
Something like:
def validate_custom_values
custom_field_values
.select { |cfv| cfv.custom_field.in?(custom_fields_to_validate) }
.uniq
.reject { |cv| cv.marked_for_destruction? || cv.calculated_value? }
.select(&:invalid?)
.each { |custom_value| add_custom_value_errors! custom_value }
endSince this requires a bigger change, I created a maintenance ticket to address this separately.
| let(:contract_options) { { skip_custom_field_validation: true } } | ||
| let(:project) { create(:project) } | ||
|
|
||
| it "deactivates custom field validations" do |
There was a problem hiding this comment.
The new specs in this file check that a method is called. It does not verify anything else.
I think it should check the services result instead and verify that setting this parameter influences the validation.
There is the nice feature spec that does check the change in validation already, but since the AttributeService is a key actor for that, it deserves its own spec.
There was a problem hiding this comment.
Well spotted, updated the specs e16e0bd .
EinLama
left a comment
There was a problem hiding this comment.
Nice. With the maintenance ticket to investigate and fix the caching trouble and the added spec, this looks good to me ✅
e16e0bd to
2e29ca3
Compare
Ticket
https://community.openproject.org/wp/69034
What are you trying to accomplish?
Screenshots
Blank project does show the required project attributes
Creating a project from templates does not show and require the project attributes
What approach did you choose and why?
SetAttributesContractwhen a special contract option is passedskip_custom_field_validation: true.template_idon the projects created from a template.Merge checklist