Commit bff7e662 authored by Alessio Caiazza's avatar Alessio Caiazza

Merge branch 'remove-namespace-becomes-namespace' into 'master'

Remove .becomes(Namespace) calls that favour N+1 queries on route model

See merge request gitlab-org/gitlab!37462
parents 8a6b484a 2c630ba9
......@@ -105,7 +105,7 @@ class Projects::EnvironmentsController < Projects::ApplicationController
action_or_env_url =
if stop_action
polymorphic_url([project.namespace.becomes(Namespace), project, stop_action])
polymorphic_url([project, stop_action])
else
project_environment_url(project, @environment)
end
......
......@@ -12,7 +12,7 @@ module AwardEmojiHelper
toggle_award_emoji_project_note_path(@project, awardable.id)
end
else
url_for([:toggle_award_emoji, @project.namespace.becomes(Namespace), @project, awardable])
url_for([:toggle_award_emoji, @project, awardable])
end
end
end
......
......@@ -2,10 +2,8 @@
module CustomMetricsHelper
def custom_metrics_data(project, metric)
custom_metrics_path = project.namespace.becomes(::Namespace)
{
'custom-metrics-path' => url_for([custom_metrics_path, project, metric]),
'custom-metrics-path' => url_for([project, metric]),
'metric-persisted' => metric.persisted?.to_s,
'edit-project-service-path' => edit_project_service_path(project, PrometheusService),
'validate-query-path' => validate_query_project_prometheus_metrics_path(project),
......
......@@ -19,7 +19,7 @@ module EnvironmentHelper
end
def deployment_path(deployment)
[deployment.project.namespace.becomes(Namespace), deployment.project, deployment.deployable]
[deployment.project, deployment.deployable]
end
def deployment_link(deployment, text: nil)
......
......@@ -199,8 +199,7 @@ module EventsHelper
elsif event.design_note?
design_url(event.note_target, anchor: dom_id(event.note))
else
polymorphic_url([event.project.namespace.becomes(Namespace),
event.project, event.note_target],
polymorphic_url([event.project, event.note_target],
anchor: dom_id(event.target))
end
end
......
......@@ -100,8 +100,12 @@ module GitlabRoutingHelper
toggle_award_emoji_snippet_path(*args)
end
def toggle_award_emoji_namespace_project_project_snippet_path(*args)
toggle_award_emoji_namespace_project_snippet_path(*args)
def toggle_award_emoji_project_project_snippet_path(*args)
toggle_award_emoji_project_snippet_path(*args)
end
def toggle_award_emoji_project_project_snippet_url(*args)
toggle_award_emoji_project_snippet_url(*args)
end
## Members
......
......@@ -126,7 +126,7 @@ module NotesHelper
if @snippet.is_a?(PersonalSnippet)
[@note]
else
[@project.namespace.becomes(Namespace), @project, @note]
[@project, @note]
end
end
......
......@@ -40,7 +40,7 @@ module TimeboxesHelper
opts = { milestone_title: milestone.title, state: state }
if @project
polymorphic_path([@project.namespace.becomes(Namespace), @project, type], opts)
polymorphic_path([@project, type], opts)
elsif @group
polymorphic_url([type, @group], opts)
else
......
......@@ -375,7 +375,6 @@ class JiraService < IssueTrackerService
def build_entity_url(noteable_type, entity_id)
polymorphic_url(
[
self.project.namespace.becomes(Namespace),
self.project,
noteable_type.to_sym
],
......
......@@ -24,7 +24,7 @@ class EventPresenter < Gitlab::View::Presenter::Delegated
when Group
[event.group, event.target]
when Project
[event.project.namespace.becomes(Namespace), event.project, event.target]
[event.project, event.target]
else
''
end
......
......@@ -74,7 +74,7 @@
- @projects.each do |project|
%li
%strong
= link_to project.full_name, [:admin, project.namespace.becomes(Namespace), project]
= link_to project.full_name, [:admin, project]
%span.badge.badge-pill
= storage_counter(project.statistics.storage_size)
%span.float-right.light
......@@ -93,7 +93,7 @@
- shared_projects.each do |project|
%li
%strong
= link_to project.full_name, [:admin, project.namespace.becomes(Namespace), project]
= link_to project.full_name, [:admin, project]
%span.badge.badge-pill
= storage_counter(project.statistics.storage_size)
%span.float-right.light
......
......@@ -37,7 +37,7 @@
%td
= link_to project.import_source, "https://code.google.com/p/#{project.import_source}", target: "_blank", rel: 'noopener noreferrer'
%td
= link_to project.full_path, [project.namespace.becomes(Namespace), project]
= link_to project.full_path, project
%td.job-status
- case project.import_status
- when 'finished'
......
<%= 'Label'.pluralize(@label_names.size) %> added: <%= @label_names.to_sentence %>
<%= url_for([issuable.project.namespace.becomes(Namespace), issuable.project, issuable, { only_path: false }]) %>
<%= url_for([issuable.project, issuable, { only_path: false }]) %>
Reassigned Issue <%= @issue.iid %>
<%= url_for([@issue.project.namespace.becomes(Namespace), @issue.project, @issue, { only_path: false }]) %>
<%= url_for([@issue.project, @issue, { only_path: false }]) %>
Assignee changed <%= "from #{sanitize_name(@previous_assignees.map(&:name).to_sentence)}" if @previous_assignees.any? -%>
to <%= "#{@issue.assignees.any? ? @issue.assignee_list : 'Unassigned'}" %>
Reassigned Merge Request <%= @merge_request.iid %>
<%= url_for([@merge_request.project.namespace.becomes(Namespace), @merge_request.project, @merge_request, { only_path: false }]) %>
<%= url_for([@merge_request.project, @merge_request, { only_path: false }]) %>
Assignee changed <%= "from #{sanitize_name(@previous_assignees.map(&:name).to_sentence)}" if @previous_assignees.any? -%>
to <%= "#{@merge_request.assignees.any? ? @merge_request.assignee_list : 'Unassigned'}" %>
......@@ -21,7 +21,7 @@
.modal-body
- if description
%p= description
= form_tag [type.underscore, @project.namespace.becomes(Namespace), @project, commit], method: :post, remote: false, class: "js-#{type}-form js-requires-input" do
= form_tag [type.underscore, @project, commit], method: :post, remote: false, class: "js-#{type}-form js-requires-input" do
.form-group.branch
= label_tag 'start_branch', branch_label, class: 'label-bold'
......
......@@ -9,7 +9,7 @@
= _('Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one.')
.settings-content
= form_for [@project.namespace.becomes(Namespace), @project], remote: true, html: { multipart: true, anchor: 'default-branch-settings' }, authenticity_token: true do |f|
= form_for @project, remote: true, html: { multipart: true, anchor: 'default-branch-settings' }, authenticity_token: true do |f|
%fieldset
- if @project.empty_repo?
.text-secondary
......
......@@ -3,7 +3,7 @@
%hr
%div
= form_for [@project.namespace.becomes(Namespace), @project, @deploy_key], include_id: false, html: { class: 'js-requires-input' } do |f|
= form_for [@project, @deploy_key], include_id: false, html: { class: 'js-requires-input' } do |f|
= render partial: 'shared/deploy_keys/form', locals: { form: f, deploy_key: @deploy_key }
.form-actions
= f.submit 'Save changes', class: 'btn-success btn'
......
......@@ -10,5 +10,5 @@
- actions.each do |action|
- next unless can?(current_user, :update_build, action)
%li
= link_to [:play, @project.namespace.becomes(Namespace), @project, action], method: :post, rel: 'nofollow' do
= link_to [:play, @project, action], method: :post, rel: 'nofollow' do
%span= action.name
......@@ -16,7 +16,7 @@
= s_('Environments|This action will run the job defined by %{environment_name} for commit %{commit_id}, putting the environment in a previous version. You can revert it by re-deploying the latest version of your application. Are you sure you want to continue?').html_safe % {commit_id: commit_sha, environment_name: @environment.name}
.modal-footer
= button_tag _('Cancel'), type: 'button', class: 'btn btn-cancel', data: { dismiss: 'modal' }
= link_to [:retry, @project.namespace.becomes(Namespace), @project, deployment.deployable], method: :post, class: 'btn btn-danger' do
= link_to [:retry, @project, deployment.deployable], method: :post, class: 'btn btn-danger' do
- if deployment.last?
= s_('Environments|Re-deploy')
- else
......
......@@ -17,7 +17,7 @@
%p= _('Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions.')
.settings-content
= form_for [@project.namespace.becomes(Namespace), @project], remote: true, html: { multipart: true, class: "sharing-permissions-form" }, authenticity_token: true do |f|
= form_for @project, remote: true, html: { multipart: true, class: "sharing-permissions-form" }, authenticity_token: true do |f|
%input{ name: 'update_section', type: 'hidden', value: 'js-shared-permissions' }
%template.js-project-permissions-form-data{ type: "application/json" }= project_permissions_panel_data_json(@project)
.js-project-permissions-form
......@@ -34,7 +34,7 @@
.settings-content
= render_if_exists 'shared/promotions/promote_mr_features'
= form_for [@project.namespace.becomes(Namespace), @project], remote: true, html: { multipart: true, class: "merge-request-settings-form js-mr-settings-form" }, authenticity_token: true do |f|
= form_for @project, remote: true, html: { multipart: true, class: "merge-request-settings-form js-mr-settings-form" }, authenticity_token: true do |f|
%input{ name: 'update_section', type: 'hidden', value: 'js-merge-request-settings' }
= render 'projects/merge_request_settings', form: f
= f.submit _('Save changes'), class: "btn btn-success qa-save-merge-request-changes rspec-save-merge-request-changes"
......@@ -77,7 +77,7 @@
.sub-section.rename-repository
%h4.warning-title= _('Change path')
= render 'projects/errors'
= form_for([@project.namespace.becomes(Namespace), @project]) do |f|
= form_for @project do |f|
.form-group
= f.label :path, _('Path'), class: 'label-bold'
.form-group
......@@ -96,7 +96,7 @@
- if can?(current_user, :change_namespace, @project)
.sub-section
%h4.danger-title= _('Transfer project')
= form_for([@project.namespace.becomes(Namespace), @project], url: transfer_project_path(@project), method: :put, remote: true, html: { class: 'js-project-transfer-form' } ) do |f|
= form_for @project, url: transfer_project_path(@project), method: :put, remote: true, html: { class: 'js-project-transfer-form' } do |f|
.form-group
= label_tag :new_namespace_id, nil, class: 'label-bold' do
%span= _('Select a new namespace')
......@@ -114,7 +114,7 @@
%h4.danger-title= _('Remove fork relationship')
%p= remove_fork_project_description_message(@project)
= form_for([@project.namespace.becomes(Namespace), @project], url: remove_fork_project_path(@project), method: :delete, remote: true, html: { class: 'transfer-project' }) do |f|
= form_for @project, url: remove_fork_project_path(@project), method: :delete, remote: true, html: { class: 'transfer-project' } do |f|
%p
%strong= _('Once removed, the fork relationship cannot be restored and you will no longer be able to send merge requests to the source.')
= button_to _('Remove fork relationship'), '#', class: "btn btn-remove js-confirm-danger", data: { "confirm-danger-message" => remove_fork_project_warning_message(@project) }
......
......@@ -6,7 +6,7 @@
- link_to_read_more = link_to(_("More information"), help_page_path("ci/environments/index.md"))
= _("Environments allow you to track deployments of your application %{link_to_read_more}.").html_safe % { link_to_read_more: link_to_read_more }
= form_for [@project.namespace.becomes(Namespace), @project, @environment], html: { class: 'col-lg-9' } do |f|
= form_for [@project, @environment], html: { class: 'col-lg-9' } do |f|
= form_errors(@environment)
.form-group
......
......@@ -7,7 +7,7 @@
= render 'shared/web_hooks/title_and_docs', hook: @hook
.col-lg-9.gl-mb-3
= form_for [@project.namespace.becomes(Namespace), @project, @hook], as: :hook, url: project_hook_path(@project, @hook) do |f|
= form_for [@project, @hook], as: :hook, url: project_hook_path(@project, @hook) do |f|
= render partial: 'shared/web_hooks/form', locals: { form: f, hook: @hook }
%span>= f.submit 'Save changes', class: 'btn btn-success gl-mr-3'
......
......@@ -7,7 +7,7 @@
= render 'shared/web_hooks/title_and_docs', hook: @hook
.col-lg-8.gl-mb-3
= form_for @hook, as: :hook, url: polymorphic_path([@project.namespace.becomes(Namespace), @project, :hooks]) do |f|
= form_for @hook, as: :hook, url: polymorphic_path([@project, :hooks]) do |f|
= render partial: 'shared/web_hooks/form', locals: { form: f, hook: @hook }
= f.submit 'Add webhook', class: 'btn btn-success'
......
= form_for [@project.namespace.becomes(Namespace), @project, @issue],
= form_for [@project, @issue],
html: { class: 'issue-form common-note-form js-quick-submit js-requires-input' } do |f|
= render 'shared/issuable/form', f: f, issuable: @issue
- form = [@project.namespace.becomes(Namespace), @project, @issue]
= render layout: 'layouts/recaptcha_verification', locals: { spammable: @issue, form: form } do
= render layout: 'layouts/recaptcha_verification', locals: { spammable: @issue } do
= hidden_field_tag(:merge_request_to_resolve_discussions_of, params[:merge_request_to_resolve_discussions_of])
= hidden_field_tag(:discussion_to_resolve, params[:discussion_to_resolve])
= form_for [@project.namespace.becomes(Namespace), @project, @merge_request],
= form_for [@project, @merge_request],
html: { class: 'merge-request-form common-note-form js-requires-input js-quick-submit' } do |f|
= render 'shared/issuable/form', f: f, issuable: @merge_request, presenter: @mr_presenter
%h3.page-title
New Merge Request
= form_for [@project.namespace.becomes(Namespace), @project, @merge_request], url: project_new_merge_request_path(@project), method: :get, html: { class: "merge-request-form js-requires-input" } do |f|
= form_for [@project, @merge_request], url: project_new_merge_request_path(@project), method: :get, html: { class: "merge-request-form js-requires-input" } do |f|
- if params[:nav_source].present?
= hidden_field_tag(:nav_source, params[:nav_source])
.hide.alert.alert-danger.mr-compare-errors
......
%h3.page-title
New Merge Request
= form_for [@project.namespace.becomes(Namespace), @project, @merge_request], html: { class: 'merge-request-form common-note-form js-requires-input js-quick-submit' } do |f|
= form_for [@project, @merge_request], html: { class: 'merge-request-form common-note-form js-requires-input js-quick-submit' } do |f|
= render 'shared/issuable/form', f: f, issuable: @merge_request, commits: @commits, presenter: @mr_presenter
= f.hidden_field :source_project_id
= f.hidden_field :source_branch
......
= form_for [@project.namespace.becomes(Namespace), @project, @milestone],
= form_for [@project, @milestone],
html: { class: 'milestone-form common-note-form js-quick-submit js-requires-input' } do |f|
= form_errors(@milestone)
.row
......
= form_for @project, url: namespace_project_pages_path(@project.namespace.becomes(Namespace), @project), html: { class: 'inline', title: pages_https_only_title } do |f|
= form_for @project, url: project_pages_path(@project), html: { class: 'inline', title: pages_https_only_title } do |f|
- if Gitlab.config.pages.external_http || Gitlab.config.pages.external_https
= render_if_exists 'shared/pages/max_pages_size_input', form: f
......
......@@ -4,7 +4,7 @@
= _("New Pages Domain")
= render 'projects/pages_domains/helper_text'
%div
= form_for [@project.namespace.becomes(Namespace), @project, domain_presenter], html: { class: 'fieldset-form' } do |f|
= form_for [@project, domain_presenter], html: { class: 'fieldset-form' } do |f|
= render 'form', { f: f }
.form-actions
= f.submit _('Create New Domain'), class: "btn btn-success"
......
......@@ -14,7 +14,7 @@
= _('Pages Domain')
= render 'projects/pages_domains/helper_text'
%div
= form_for [@project.namespace.becomes(Namespace), @project, domain_presenter], html: { class: 'fieldset-form' } do |f|
= form_for [@project, domain_presenter], html: { class: 'fieldset-form' } do |f|
= render 'form', { f: f }
.form-actions.d-flex.justify-content-between
= f.submit _('Save Changes'), class: "btn btn-success"
......
= form_for [@project.namespace.becomes(Namespace), @project, @schedule], as: :schedule, html: { id: "new-pipeline-schedule-form", class: "js-pipeline-schedule-form pipeline-schedule-form" } do |f|
= form_for [@project, @schedule], as: :schedule, html: { id: "new-pipeline-schedule-form", class: "js-pipeline-schedule-form pipeline-schedule-form" } do |f|
= form_errors(@schedule)
.form-group.row
.col-md-9
......
= form_for [@project.namespace.becomes(Namespace), @project, @protected_branch], html: { class: 'new-protected-branch js-new-protected-branch' } do |f|
= form_for [@project, @protected_branch], html: { class: 'new-protected-branch js-new-protected-branch' } do |f|
%input{ type: 'hidden', name: 'update_section', value: 'js-protected-branches-settings' }
.card
.card-header
......
......@@ -20,4 +20,4 @@
- if can_admin_project
%td
= link_to 'Unprotect', [@project.namespace.becomes(Namespace), @project, protected_branch, { update_section: 'js-protected-branches-settings' }], disabled: local_assigns[:disabled], data: { confirm: 'Branch will be writable for developers. Are you sure?' }, method: :delete, class: "btn btn-warning"
= link_to 'Unprotect', [@project, protected_branch, { update_section: 'js-protected-branches-settings' }], disabled: local_assigns[:disabled], data: { confirm: 'Branch will be writable for developers. Are you sure?' }, method: :delete, class: "btn btn-warning"
= form_for [@project.namespace.becomes(Namespace), @project, @protected_tag], html: { class: 'new-protected-tag js-new-protected-tag' } do |f|
= form_for [@project, @protected_tag], html: { class: 'new-protected-tag js-new-protected-tag' } do |f|
%input{ type: 'hidden', name: 'update_section', value: 'js-protected-tags-settings' }
.card
.card-header
......
......@@ -19,4 +19,4 @@
- if can? current_user, :admin_project, @project
%td
= link_to 'Unprotect', [@project.namespace.becomes(Namespace), @project, protected_tag, { update_section: 'js-protected-tags-settings' }], data: { confirm: 'Tag will be writable for developers. Are you sure?' }, method: :delete, class: 'btn btn-warning'
= link_to 'Unprotect', [@project, protected_tag, { update_section: 'js-protected-tags-settings' }], data: { confirm: 'Tag will be writable for developers. Are you sure?' }, method: :delete, class: 'btn btn-warning'
......@@ -27,7 +27,7 @@
- runner_project = @project.runner_projects.find_by(runner_id: runner) # rubocop: disable CodeReuse/ActiveRecord
= link_to _('Disable for this project'), project_runner_project_path(@project, runner_project), data: { confirm: _("Are you sure?") }, method: :delete, class: 'btn btn-danger btn-sm'
- elsif runner.project_type?
= form_for [@project.namespace.becomes(Namespace), @project, @project.runner_projects.new] do |f|
= form_for [@project, @project.runner_projects.new] do |f|
= f.hidden_field :runner_id, value: runner.id
= f.submit _('Enable for this project'), class: 'btn btn-sm'
.float-right
......
= form_for [@project.namespace.becomes(Namespace), @project], remote: true, html: { multipart: true, class: "edit-project js-general-settings-form" }, authenticity_token: true do |f|
= form_for [@project], remote: true, html: { multipart: true, class: "edit-project js-general-settings-form" }, authenticity_token: true do |f|
%input{ name: 'update_section', type: 'hidden', value: 'js-general-settings' }
= form_errors(@project)
......
- form = [@project.namespace.becomes(Namespace), @project, @snippet.becomes(Snippet)]
= render 'layouts/recaptcha_verification', spammable: @snippet, form: form
= render 'layouts/recaptcha_verification', spammable: @snippet
= form_for [@project.namespace.becomes(Namespace), @project, @trigger], html: { class: 'gl-show-field-errors' } do |f|
= form_for [@project, @trigger], html: { class: 'gl-show-field-errors' } do |f|
= form_errors(@trigger)
- if @trigger.token
......
......@@ -8,7 +8,7 @@
= search_entries_info(@search_objects, @scope, @search_term)
- unless @show_snippets
- if @project
- link_to_project = link_to(@project.full_name, [@project.namespace.becomes(Namespace), @project], class: 'ml-md-1')
- link_to_project = link_to(@project.full_name, @project, class: 'ml-md-1')
- if @scope == 'blobs'
- repository_ref = params[:repository_ref].to_s.presence || @project.default_branch
= s_("SearchCodeResults|in")
......
.search-result-row
%h4
= confidential_icon(issue)
= link_to namespace_project_issue_path(issue.project.namespace.becomes(Namespace), issue.project, issue) do
= link_to project_issue_path(issue.project, issue) do
%span.term.str-truncated= issue.title
- if issue.closed?
%span.badge.badge-danger.gl-ml-2= _("Closed")
......
.search-result-row
%h4
= link_to namespace_project_merge_request_path(merge_request.target_project.namespace.becomes(Namespace), merge_request.target_project, merge_request) do
= link_to project_merge_request_path(merge_request.target_project, merge_request) do
%span.term.str-truncated= merge_request.title
- if merge_request.merged?
%span.badge.badge-primary.gl-ml-2= _("Merged")
......
.search-result-row
%h4
= link_to namespace_project_milestone_path(milestone.project.namespace.becomes(Namespace), milestone.project, milestone) do
= link_to project_milestone_path(milestone.project, milestone) do
%span.term.str-truncated= milestone.title
- if milestone.description.present?
......
......@@ -3,7 +3,7 @@
- noteable_text = show_unsubscribe_title?(noteable) ? %(#{noteable.title} (#{noteable.to_reference})) : %(#{noteable.to_reference})
- show_project_path = can_read_project?(@sent_notification.project)
- project_path = show_project_path ? @sent_notification.project.full_name : _("GitLab / Unsubscribe")
- noteable_url = show_project_path ? url_for([@sent_notification.project.namespace.becomes(Namespace), @sent_notification.project, noteable]) : breadcrumb_title_link
- noteable_url = show_project_path ? url_for([@sent_notification.project, noteable]) : breadcrumb_title_link
- page_title _('Unsubscribe'), noteable_text, noteable_type.pluralize, project_path
%h3.page-title
......
= form_for [@project.namespace.becomes(Namespace), @project, @deploy_keys.new_key], url: namespace_project_deploy_keys_path, html: { class: "js-requires-input container" } do |f|
= form_for [@project.namespace, @project, @deploy_keys.new_key], url: namespace_project_deploy_keys_path, html: { class: "js-requires-input container" } do |f|
= form_errors(@deploy_keys.new_key)
.form-group.row
= f.label :title, class: "label-bold"
......
......@@ -4,7 +4,7 @@
%aside.issues-bulk-update.js-right-sidebar.right-sidebar{ "aria-live" => "polite", data: { 'signed-in': current_user.present? } }
.issuable-sidebar.hidden
= form_tag [:bulk_update, @project.namespace.becomes(Namespace), @project, type], method: :post, class: "bulk-update" do
= form_tag [:bulk_update, @project, type], method: :post, class: "bulk-update" do
.block.issuable-sidebar-header
.filter-item.inline.update-issues-btn.float-left
= button_tag _('Update all'), class: "btn update-selected-issues btn-info", disabled: true
......
......@@ -9,7 +9,7 @@
.alert.alert-danger
Someone edited the #{issuable.class.model_name.human.downcase} the same time you did.
Please check out
= link_to "the #{issuable.class.model_name.human.downcase}", polymorphic_path([@project.namespace.becomes(Namespace), @project, issuable]), target: "_blank", rel: 'noopener noreferrer'
= link_to "the #{issuable.class.model_name.human.downcase}", polymorphic_path([@project, issuable]), target: "_blank", rel: 'noopener noreferrer'
and make sure your changes will not unintentionally remove theirs
= render 'shared/issuable/form/branch_chooser', issuable: issuable, form: form
......@@ -63,11 +63,11 @@
.row-content-block{ class: (is_footer ? "footer-block" : "middle-block") }
.float-right
- if issuable.new_record?
= link_to 'Cancel', polymorphic_path([@project.namespace.becomes(Namespace), @project, issuable.class]), class: 'btn btn-cancel'
= link_to 'Cancel', polymorphic_path([@project, issuable.class]), class: 'btn btn-cancel'
- else
- if can?(current_user, :"destroy_#{issuable.to_ability_name}", @project)
= link_to 'Delete', polymorphic_path([@project.namespace.becomes(Namespace), @project, issuable], params: { destroy_confirm: true }), data: { confirm: "#{issuable.human_class_name} will be removed! Are you sure?" }, method: :delete, class: 'btn btn-danger btn-grouped'
= link_to 'Cancel', polymorphic_path([@project.namespace.becomes(Namespace), @project, issuable]), class: 'btn btn-grouped btn-cancel'
= link_to 'Delete', polymorphic_path([@project, issuable], params: { destroy_confirm: true }), data: { confirm: "#{issuable.human_class_name} will be removed! Are you sure?" }, method: :delete, class: 'btn btn-danger btn-grouped'
= link_to 'Cancel', polymorphic_path([@project, issuable]), class: 'btn btn-grouped btn-cancel'
%span.gl-mr-3
- if issuable.new_record?
......
- form = [@snippet.becomes(Snippet)]
= render 'layouts/recaptcha_verification', spammable: @snippet, form: form
= render 'layouts/recaptcha_verification', spammable: @snippet
......@@ -20,7 +20,7 @@
- if event.note?
= link_to event.note_target.to_reference, event_note_target_url(event), class: 'has-tooltip', title: event.target_title
- elsif event.target
= link_to event.target.to_reference, [event.project.namespace.becomes(Namespace), event.project, event.target], class: 'has-tooltip', title: event.target_title
= link_to event.target.to_reference, [event.project, event.target], class: 'has-tooltip', title: event.target_title
= s_('UserProfile|at')
%strong
......
......@@ -10,7 +10,7 @@
= link_to _("Learn more about approvals."), help_page_path("user/project/merge_requests/merge_request_approvals"), target: '_blank'
.settings-content
= form_for [@project.namespace.becomes(Namespace), @project], remote: true, html: { class: "merge-request-approval-settings-form js-mr-approvals-form" }, authenticity_token: true do |f|
= form_for @project, remote: true, html: { class: "merge-request-approval-settings-form js-mr-approvals-form" }, authenticity_token: true do |f|
%input{ name: 'update_section', type: 'hidden', value: 'js-merge-request-approval-settings' }
= render 'projects/merge_request_approvals_settings_form', form: f, project: @project
= f.submit _("Save changes"), class: "btn btn-success qa-save-merge-request-approval-settings-button"
= form_for [@project.namespace.becomes(Namespace), @project, @protected_environment], html: { class: 'new-protected-environment js-new-protected-environment' } do |f|
= form_for [@project, @protected_environment], html: { class: 'new-protected-environment js-new-protected-environment' } do |f|
.card
.card-header
%h3.card-title
......
......@@ -9,4 +9,4 @@
- if can_admin_project
%td
= link_to s_('ProtectedEnvironment|Unprotect'), [@project.namespace.becomes(Namespace), @project, protected_environment], disabled: local_assigns[:disabled], data: { confirm: s_('ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?') % { environment_name: protected_environment.name } }, method: :delete, class: 'btn btn-warning'
= link_to s_('ProtectedEnvironment|Unprotect'), [@project, protected_environment], disabled: local_assigns[:disabled], data: { confirm: s_('ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?') % { environment_name: protected_environment.name } }, method: :delete, class: 'btn btn-warning'
......@@ -12,7 +12,7 @@
.settings-content
%h5
Add new push rule
= form_for [@project.namespace.becomes(Namespace), @project, @push_rule] do |f|
= form_for [@project, @push_rule] do |f|
= form_errors(@push_rule)
= render "shared/push_rules/form", f: f, context: @project
......@@ -7,7 +7,7 @@
%p= _('Set a default template for issue descriptions.')
.settings-content
= form_for [@project.namespace.becomes(Namespace), @project], remote: true, html: { multipart: true, class: "issue-settings-form" }, authenticity_token: true do |f|
= form_for @project, remote: true, html: { multipart: true, class: "issue-settings-form" }, authenticity_token: true do |f|
%input{ type: 'hidden', name: 'update_section', value: 'js-issue-settings' }
.row
.form-group.col-md-9
......
......@@ -9,7 +9,7 @@ RSpec.describe 'routes to the proper webhooks controller', type: :routing do
it 'routes the test action' do
expect(
post: polymorphic_path([project.namespace.becomes(Namespace), project, project_hook], action: :test)
post: polymorphic_path([project, project_hook], action: :test)
).to route_to(controller: 'projects/hooks',
action: 'test',
namespace_id: project.namespace.path,
......@@ -19,7 +19,7 @@ RSpec.describe 'routes to the proper webhooks controller', type: :routing do
it 'routes a single record' do
expect(
delete: polymorphic_path([project.namespace.becomes(Namespace), project, project_hook])
delete: polymorphic_path([project, project_hook])
).to route_to(controller: 'projects/hooks',
action: 'destroy',
namespace_id: project.namespace.path,
......
......@@ -45,7 +45,7 @@ module Gitlab
reverts_for_type('namespace') do |path_before_rename, current_path|
matches_path = MigrationClasses::Route.arel_table[:path].matches(current_path)
namespace = MigrationClasses::Namespace.joins(:route)
.find_by(matches_path)&.becomes(MigrationClasses::Namespace)
.find_by(matches_path)&.becomes(MigrationClasses::Namespace) # rubocop: disable Cop/AvoidBecomes
if namespace
perform_rename(namespace, current_path, path_before_rename)
......
......@@ -69,7 +69,6 @@ module Gitlab
def resource_url
url_for(
[
resource.project.namespace.becomes(Namespace),
resource.project,
resource
]
......
......@@ -22,7 +22,7 @@ module Gitlab
def attachments
resource.map do |issue|
url = "[#{issue.to_reference}](#{url_for([namespace, project, issue])})"
url = "[#{issue.to_reference}](#{url_for([project, issue])})"
{
color: color(issue),
......@@ -39,10 +39,6 @@ module Gitlab
def project
@project ||= resource.first.project
end
def namespace
@namespace ||= project.namespace.becomes(Namespace)
end
end
end
end
......
# frozen_string_literal: true
module RuboCop
module Cop
# Cop that blacklists the use of ".becomes(SomeConstant)".
#
# The use of becomes() will result in a new object being created, throwing
# away any eager loaded assocations. This in turn can cause N+1 query
# problems, even when a developer eager loaded all necessary associations.
#
# See https://gitlab.com/gitlab-org/gitlab/-/issues/23182 for more information.
class AvoidBecomes < RuboCop::Cop::Cop
MSG = 'Avoid the use of becomes(SomeConstant), as this creates a ' \
'new object and throws away any eager loaded associations. ' \
'When creating URLs in views, just use the path helpers directly. ' \
'For example, instead of `link_to(..., [group.becomes(Namespace), ...])` ' \
'use `link_to(..., namespace_foo_path(group, ...))`. Most of the time there is no ' \
'need to pass in namespace to the path helpers after implementaton of ' \
'https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/12566'
def_node_matcher :becomes?, <<~PATTERN
(send {send ivar lvar} :becomes ...)
PATTERN
def on_send(node)
add_offense(node, location: :expression) if becomes?(node)
end
end
end
end
......@@ -334,7 +334,7 @@ RSpec.describe Projects::MergeRequestsController do
it 'closes MR without errors' do
update_merge_request(state_event: 'close')
expect(response).to redirect_to([merge_request.target_project.namespace.becomes(Namespace), merge_request.target_project, merge_request])
expect(response).to redirect_to([merge_request.target_project, merge_request])
expect(merge_request.reload.closed?).to be_truthy
end
......@@ -343,7 +343,7 @@ RSpec.describe Projects::MergeRequestsController do
update_merge_request(title: 'New title')
expect(response).to redirect_to([merge_request.target_project.namespace.becomes(Namespace), merge_request.target_project, merge_request])
expect(response).to redirect_to([merge_request.target_project, merge_request])
expect(merge_request.reload.title).to eq 'New title'
end
......
......@@ -284,7 +284,7 @@ RSpec.describe NotesHelper do
@snippet = create(:project_snippet, project: @project)
@note = create(:note_on_personal_snippet)
expect(helper.form_resources).to eq([@project.namespace, @project, @note])
expect(helper.form_resources).to eq([@project, @note])
end
it 'returns namespace, project and note path for other noteables' do
......@@ -292,7 +292,7 @@ RSpec.describe NotesHelper do
@project = create(:project, path: 'test', namespace: namespace)
@note = create(:note_on_issue, project: @project)
expect(helper.form_resources).to eq([@project.namespace, @project, @note])
expect(helper.form_resources).to eq([@project, @note])
end
end
......
......@@ -14,7 +14,7 @@ RSpec.describe ManualInverseAssociation do
stub_const("#{described_class}::Model", model)
end
let(:instance) { create(:merge_request).becomes(model) }
let(:instance) { create(:merge_request).becomes(model) } # rubocop: disable Cop/AvoidBecomes
describe '.manual_inverse_association' do
context 'when the relation exists' do
......
......@@ -35,7 +35,7 @@ RSpec.describe EventPresenter do
context 'with project label' do
subject { project_event.present.target_link_options }
it { is_expected.to eq([group.becomes(Namespace), project, target]) }
it { is_expected.to eq([project, target]) }
end
end
end
# frozen_string_literal: true
require 'fast_spec_helper'
require 'rubocop'
require 'rubocop/rspec/support'
require_relative '../../../rubocop/cop/avoid_becomes'
RSpec.describe RuboCop::Cop::AvoidBecomes, type: :rubocop do
include CopHelper
subject(:cop) { described_class.new }
it 'flags the use of becomes with a constant parameter' do
inspect_source('foo.becomes(Project)')
expect(cop.offenses.size).to eq(1)
end
it 'flags the use of becomes with a namespaced constant parameter' do
inspect_source('foo.becomes(Namespace::Group)')
expect(cop.offenses.size).to eq(1)
end
it 'flags the use of becomes with a dynamic parameter' do
inspect_source(<<~RUBY)
model = Namespace
project = Project.first
project.becomes(model)
RUBY
expect(cop.offenses.size).to eq(1)
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment