Fix inconsistent memory association for ProjectNamespace / Project
What does this MR do and why?
Currently the inverse_of
relationship is not used due to some technical debt on Project that needs to be resolved. It results in a loaded Project and its ProjectNamespace having inconsistent objects loaded in memory. This MR adds the inverse_of
relationship so that they are more performant and consistent
See https://github.com/rails/rails/issues/8125 and https://www.viget.com/articles/exploring-the-inverse-of-option-on-rails-model-associations/ for some context, and !89311 (closed) for prior art
Screenshots or screen recordings
There should be no detectable user-facing changes
How to set up and validate locally
This was initially detected in specs with following code:
p = create(:project)
p.project_namespace.project == nil # this returns true
However loading the project does not result in the same issue:
p = Project.find(project.id)
p.project_namespace.project == nil # this returns false
This can also be reproduced from a rails console through Projects::CreateService
[1] pry(main)> group = Group.first
[2] pry(main)> params = {
[2] pry(main)* namespace_id: group.id,
[2] pry(main)* name: 'test1'.titleize,
[2] pry(main)* path: 'test1',
[2] pry(main)* description: FFaker::Lorem.sentence,
[2] pry(main)* visibility_level: Gitlab::VisibilityLevel::PRIVATE,
[2] pry(main)* skip_disk_validation: true
[2] pry(main)* }
=> {:namespace_id=>22, :name=>"Test1", :path=>"test1", :description=>"Omnis distinctio omnis nemo sequi atque voluptate non.", :visibility_level=>0, :skip_disk_validation=>true}
[3] pry(main)> project = ::Projects::CreateService.new(User.first, params).execute
[4] pry(main)> project.project_namespace.project
=> nil
With the change:
[156] pry(main)> group = Group.first
[157] pry(main)> params = { namespace_id: group.id, name: 'name15', path: 'name15', visibility_level: Gitlab::VisibilityLevel::PRIVATE }
=> {:namespace_id=>22, :name=>"name15", :path=>"name15", :visibility_level=>0}
[158] pry(main)> project = ::Projects::CreateService.new(User.first, params).execute
[159] pry(main)> project.project_namespace.association(:mirror_project).loaded?
=> true
[160] pry(main)> project.project_namespace.association(:project).loaded?
=> false
[161] pry(main)> project.project_namespace.project
=> nil
[162] pry(main)> project.project_namespace.mirror_project
=> #<Project id: gitlab-org/name15>>
MR acceptance checklist
This checklist encourages us to confirm any changes have been analyzed to reduce risks in quality, performance, reliability, security, and maintainability.
-
I have evaluated the MR acceptance checklist for this MR.
Related to #364277 (closed)