Skip to content
Snippets Groups Projects
Verified Commit f1926b32 authored by Markus Koller's avatar Markus Koller
Browse files

Add controller concern for paginated collections

We had similar code in a few places to redirect to the last page if
the given page number is out of range. This unifies the handling in a
new controller concern and adds usage of it in all snippet listings.
parent 60755fbc
No related branches found
No related tags found
No related merge requests found
Showing
with 145 additions and 133 deletions
Loading
Loading
@@ -2,6 +2,7 @@
 
module IssuableCollections
extend ActiveSupport::Concern
include PaginatedCollection
include SortingHelper
include SortingPreference
include Gitlab::IssuableMetadata
Loading
Loading
@@ -17,8 +18,11 @@ module IssuableCollections
def set_issuables_index
@issuables = issuables_collection
 
set_pagination
return if redirect_out_of_range(@total_pages)
unless pagination_disabled?
set_pagination
return if redirect_out_of_range(@issuables, @total_pages)
end
 
if params[:label_name].present? && @project
labels_params = { project_id: @project.id, title: params[:label_name] }
Loading
Loading
@@ -38,12 +42,10 @@ module IssuableCollections
end
 
def set_pagination
return if pagination_disabled?
@issuables = @issuables.page(params[:page])
@issuables = per_page_for_relative_position if params[:sort] == 'relative_position'
@issuable_meta_data = issuable_meta_data(@issuables, collection_type, current_user)
@total_pages = issuable_page_count
@total_pages = issuable_page_count(@issuables)
end
# rubocop:enable Gitlab/ModuleWithInstanceVariables
 
Loading
Loading
@@ -57,20 +59,8 @@ module IssuableCollections
end
# rubocop: enable CodeReuse/ActiveRecord
 
def redirect_out_of_range(total_pages)
return false if total_pages.nil? || total_pages.zero?
out_of_range = @issuables.current_page > total_pages # rubocop:disable Gitlab/ModuleWithInstanceVariables
if out_of_range
redirect_to(url_for(safe_params.merge(page: total_pages, only_path: true)))
end
out_of_range
end
def issuable_page_count
page_count_for_relation(@issuables, finder.row_count) # rubocop:disable Gitlab/ModuleWithInstanceVariables
def issuable_page_count(relation)
page_count_for_relation(relation, finder.row_count)
end
 
def page_count_for_relation(relation, row_count)
Loading
Loading
# frozen_string_literal: true
module PaginatedCollection
extend ActiveSupport::Concern
private
def redirect_out_of_range(collection, total_pages = collection.total_pages)
return false if total_pages.zero?
out_of_range = collection.current_page > total_pages
if out_of_range
redirect_to(url_for(safe_params.merge(page: total_pages, only_path: true)))
end
out_of_range
end
end
# frozen_string_literal: true
 
class Dashboard::SnippetsController < Dashboard::ApplicationController
include PaginatedCollection
include Gitlab::NoteableMetadata
 
skip_cross_project_access_check :index
Loading
Loading
@@ -11,6 +12,8 @@ class Dashboard::SnippetsController < Dashboard::ApplicationController
.page(params[:page])
.inc_author
 
return if redirect_out_of_range(@snippets)
@noteable_meta_data = noteable_meta_data(@snippets, 'Snippet')
end
end
Loading
Loading
@@ -2,6 +2,7 @@
 
class Dashboard::TodosController < Dashboard::ApplicationController
include ActionView::Helpers::NumberHelper
include PaginatedCollection
 
before_action :authorize_read_project!, only: :index
before_action :authorize_read_group!, only: :index
Loading
Loading
@@ -12,7 +13,7 @@ class Dashboard::TodosController < Dashboard::ApplicationController
@todos = @todos.page(params[:page])
@todos = @todos.with_entity_associations
 
return if redirect_out_of_range(@todos)
return if redirect_out_of_range(@todos, todos_page_count(@todos))
end
 
def destroy
Loading
Loading
@@ -82,28 +83,15 @@ class Dashboard::TodosController < Dashboard::ApplicationController
}
end
 
def todo_params
params.permit(:action_id, :author_id, :project_id, :type, :sort, :state, :group_id)
end
# rubocop: disable CodeReuse/ActiveRecord
def redirect_out_of_range(todos)
total_pages =
if todo_params.except(:sort, :page).empty?
(current_user.todos_pending_count.to_f / todos.limit_value).ceil
else
todos.total_pages
end
return false if total_pages.zero?
out_of_range = todos.current_page > total_pages
if out_of_range
redirect_to url_for(safe_params.merge(page: total_pages, only_path: true))
def todos_page_count(todos)
if todo_params.except(:sort, :page).empty? # rubocop: disable CodeReuse/ActiveRecord
(current_user.todos_pending_count.to_f / todos.limit_value).ceil
else
todos.total_pages
end
end
 
out_of_range
def todo_params
params.permit(:action_id, :author_id, :project_id, :type, :sort, :state, :group_id)
end
# rubocop: enable CodeReuse/ActiveRecord
end
# frozen_string_literal: true
 
class Explore::SnippetsController < Explore::ApplicationController
include PaginatedCollection
include Gitlab::NoteableMetadata
 
def index
Loading
Loading
@@ -9,6 +10,8 @@ class Explore::SnippetsController < Explore::ApplicationController
.page(params[:page])
.inc_author
 
return if redirect_out_of_range(@snippets)
@noteable_meta_data = noteable_meta_data(@snippets, 'Snippet')
end
end
Loading
Loading
@@ -6,6 +6,7 @@ class Projects::SnippetsController < Projects::ApplicationController
include SpammableActions
include SnippetsActions
include RendersBlob
include PaginatedCollection
include Gitlab::NoteableMetadata
 
skip_before_action :verify_authenticity_token,
Loading
Loading
@@ -34,9 +35,7 @@ class Projects::SnippetsController < Projects::ApplicationController
.page(params[:page])
.inc_author
 
if @snippets.out_of_range? && @snippets.total_pages != 0
return redirect_to project_snippets_path(@project, page: @snippets.total_pages)
end
return if redirect_out_of_range(@snippets)
 
@noteable_meta_data = noteable_meta_data(@snippets, 'Snippet')
end
Loading
Loading
Loading
Loading
@@ -7,6 +7,7 @@ class SnippetsController < ApplicationController
include SnippetsActions
include RendersBlob
include PreviewMarkdown
include PaginatedCollection
include Gitlab::NoteableMetadata
 
skip_before_action :verify_authenticity_token,
Loading
Loading
@@ -37,6 +38,8 @@ class SnippetsController < ApplicationController
.page(params[:page])
.inc_author
 
return if redirect_out_of_range(@snippets)
@noteable_meta_data = noteable_meta_data(@snippets, 'Snippet')
 
render 'index'
Loading
Loading
# frozen_string_literal: true
require 'spec_helper'
describe Dashboard::SnippetsController do
let(:user) { create(:user) }
before do
sign_in(user)
end
describe 'GET #index' do
it_behaves_like 'paginated collection' do
let(:collection) { Snippet.all }
before do
create(:personal_snippet, :public, author: user)
end
end
end
end
Loading
Loading
@@ -82,35 +82,15 @@ describe Dashboard::TodosController do
end
end
 
context 'when using pagination' do
let(:last_page) { user.todos.page.total_pages }
it_behaves_like 'paginated collection' do
let!(:issues) { create_list(:issue, 3, project: project, assignees: [user]) }
let(:collection) { user.todos }
 
before do
issues.each { |issue| todo_service.new_issue(issue, user) }
allow(Kaminari.config).to receive(:default_per_page).and_return(2)
end
 
it 'redirects to last_page if page number is larger than number of pages' do
get :index, params: { page: (last_page + 1).to_param }
expect(response).to redirect_to(dashboard_todos_path(page: last_page))
end
it 'goes to the correct page' do
get :index, params: { page: last_page }
expect(assigns(:todos).current_page).to eq(last_page)
expect(response).to have_gitlab_http_status(200)
end
it 'does not redirect to external sites when provided a host field' do
external_host = "www.example.com"
get :index, params: { page: (last_page + 1).to_param, host: external_host }
expect(response).to redirect_to(dashboard_todos_path(page: last_page))
end
context 'when providing no filters' do
it 'does not perform a query to get the page count, but gets that from the user' do
allow(controller).to receive(:current_user).and_return(user)
Loading
Loading
# frozen_string_literal: true
require 'spec_helper'
describe Explore::SnippetsController do
describe 'GET #index' do
it_behaves_like 'paginated collection' do
let(:collection) { Snippet.all }
before do
create(:personal_snippet, :public)
end
end
end
end
Loading
Loading
@@ -71,9 +71,16 @@ describe Projects::IssuesController do
end
end
 
context 'with page param' do
let(:last_page) { project.issues.page.total_pages }
it_behaves_like 'paginated collection' do
let!(:issue_list) { create_list(:issue, 2, project: project) }
let(:collection) { project.issues }
let(:params) do
{
namespace_id: project.namespace.to_param,
project_id: project,
state: 'opened'
}
end
 
before do
sign_in(user)
Loading
Loading
@@ -81,51 +88,10 @@ describe Projects::IssuesController do
allow(Kaminari.config).to receive(:default_per_page).and_return(1)
end
 
it 'redirects to last_page if page number is larger than number of pages' do
get :index,
params: {
namespace_id: project.namespace.to_param,
project_id: project,
page: (last_page + 1).to_param
}
expect(response).to redirect_to(namespace_project_issues_path(page: last_page, state: controller.params[:state], scope: controller.params[:scope]))
end
it 'redirects to specified page' do
get :index,
params: {
namespace_id: project.namespace.to_param,
project_id: project,
page: last_page.to_param
}
expect(assigns(:issues).current_page).to eq(last_page)
expect(response).to have_gitlab_http_status(200)
end
it 'does not redirect to external sites when provided a host field' do
external_host = "www.example.com"
get :index,
params: {
namespace_id: project.namespace.to_param,
project_id: project,
page: (last_page + 1).to_param,
host: external_host
}
expect(response).to redirect_to(namespace_project_issues_path(page: last_page, state: controller.params[:state], scope: controller.params[:scope]))
end
it 'does not use pagination if disabled' do
allow(controller).to receive(:pagination_disabled?).and_return(true)
 
get :index,
params: {
namespace_id: project.namespace.to_param,
project_id: project,
page: (last_page + 1).to_param
}
get :index, params: params.merge(page: last_page + 1)
 
expect(response).to have_gitlab_http_status(200)
expect(assigns(:issues).size).to eq(2)
Loading
Loading
Loading
Loading
@@ -13,31 +13,17 @@ describe Projects::SnippetsController do
end
 
describe 'GET #index' do
context 'when page param' do
let(:last_page) { project.snippets.page.total_pages }
let!(:project_snippet) { create(:project_snippet, :public, project: project, author: user) }
it 'redirects to last_page if page number is larger than number of pages' do
get :index,
params: {
namespace_id: project.namespace,
project_id: project,
page: (last_page + 1).to_param
}
expect(response).to redirect_to(namespace_project_snippets_path(page: last_page))
it_behaves_like 'paginated collection' do
let(:collection) { project.snippets }
let(:params) do
{
namespace_id: project.namespace,
project_id: project
}
end
 
it 'redirects to specified page' do
get :index,
params: {
namespace_id: project.namespace,
project_id: project,
page: last_page.to_param
}
expect(assigns(:snippets).current_page).to eq(last_page)
expect(response).to have_gitlab_http_status(200)
before do
create(:project_snippet, :public, project: project, author: user)
end
end
 
Loading
Loading
Loading
Loading
@@ -9,6 +9,15 @@ describe SnippetsController do
let(:user) { create(:user) }
 
context 'when username parameter is present' do
it_behaves_like 'paginated collection' do
let(:collection) { Snippet.all }
let(:params) { { username: user.username } }
before do
create(:personal_snippet, :public, author: user)
end
end
it 'renders snippets of a user when username is present' do
get :index, params: { username: user.username }
 
Loading
Loading
# frozen_string_literal: true
require 'spec_helper'
shared_examples 'paginated collection' do
let(:collection) { nil }
let(:last_page) { collection.page.total_pages }
let(:action) { :index }
let(:params) { {} }
it 'renders a page number that is not ouf of range' do
get action, params: params.merge(page: last_page)
expect(response).to have_gitlab_http_status(200)
end
it 'redirects to last_page if page number is larger than number of pages' do
get action, params: params.merge(page: last_page + 1)
expect(response).to redirect_to(params.merge(page: last_page))
end
it 'does not redirect to external sites when provided a host field' do
external_host = 'www.example.com'
get action, params: params.merge(page: last_page + 1, host: external_host)
expect(response).to redirect_to(params.merge(page: last_page))
end
end
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment