Skip to content

Commit 0d151c5

Browse files
committed
Refactor sorting logic in Issues and Projects controllers to use sanitize_sort method
1 parent 5892e25 commit 0d151c5

File tree

6 files changed

+41
-33
lines changed

6 files changed

+41
-33
lines changed

app/controllers/api/v1/issues_controller.rb

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,12 @@ def index
1010

1111
scope = scope.where('issues.created_at > ?', 1.day.ago) if params[:recent].present?
1212

13-
# Define allowed sort fields with database expressions
14-
allowed_sort_fields = {
15-
'created_at' => 'issues.created_at',
16-
'updated_at' => 'issues.updated_at',
17-
'stars' => "CAST(projects.repository->>'stargazers_count' AS INTEGER)"
18-
}
19-
2013
if params[:sort].present? || params[:order].present?
21-
sort_key = params[:sort].presence || 'created_at'
22-
sort_field = allowed_sort_fields[sort_key] || 'issues.created_at'
23-
14+
sort = sanitize_sort(Issue.sortable_columns, default: 'created_at')
2415
if params[:order] == 'asc'
25-
scope = scope.order(Arel.sql(sort_field).asc.nulls_last)
16+
scope = scope.order(sort.asc.nulls_last)
2617
else
27-
scope = scope.order(Arel.sql(sort_field).desc.nulls_last)
18+
scope = scope.order(sort.desc.nulls_last)
2819
end
2920
else
3021
scope = scope.order('issues.created_at DESC')
@@ -39,11 +30,11 @@ def openclimateaction
3930
scope = Project.where(id: project_ids).active.reviewed.includes(:climatetriage_issues)
4031

4132
if params[:sort].present? || params[:order].present?
42-
sort = params[:sort].presence || 'projects.updated_at'
33+
sort = sanitize_sort(Project.sortable_columns, default: 'projects.updated_at')
4334
if params[:order] == 'asc'
44-
scope = scope.order(Arel.sql(sort).asc.nulls_last)
35+
scope = scope.order(sort.asc.nulls_last)
4536
else
46-
scope = scope.order(Arel.sql(sort).desc.nulls_last)
37+
scope = scope.order(sort.desc.nulls_last)
4738
end
4839
else
4940
scope = scope.order('projects.updated_at DESC')

app/controllers/api/v1/projects_controller.rb

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ def index
88
@projects = @projects.where(reviewed: true) if params[:reviewed] == 'true'
99

1010
if params[:sort].present? || params[:order].present?
11-
sort = params[:sort].presence || 'projects.updated_at'
11+
sort = sanitize_sort(Project.sortable_columns, default: 'projects.updated_at')
1212
if params[:order] == 'asc'
13-
@projects = @projects.order(Arel.sql(sort).asc.nulls_last)
13+
@projects = @projects.order(sort.asc.nulls_last)
1414
else
15-
@projects = @projects.order(Arel.sql(sort).desc.nulls_last)
15+
@projects = @projects.order(sort.desc.nulls_last)
1616
end
1717
end
1818

@@ -64,11 +64,11 @@ def esd
6464
@projects = Project.all.where.not(last_synced_at: nil).where(esd: true)
6565

6666
if params[:sort].present? || params[:order].present?
67-
sort = params[:sort].presence || 'projects.updated_at'
67+
sort = sanitize_sort(Project.sortable_columns, default: 'projects.updated_at')
6868
if params[:order] == 'asc'
69-
@projects = @projects.order(Arel.sql(sort).asc.nulls_last)
69+
@projects = @projects.order(sort.asc.nulls_last)
7070
else
71-
@projects = @projects.order(Arel.sql(sort).desc.nulls_last)
71+
@projects = @projects.order(sort.desc.nulls_last)
7272
end
7373
end
7474

app/controllers/application_controller.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@ def default_url_options(options = {})
88
Rails.env.production? ? { :protocol => "https" }.merge(options) : options
99
end
1010

11+
def sanitize_sort(allowed_columns, default: 'updated_at')
12+
sort_param = params[:sort].presence || default
13+
sql = allowed_columns[sort_param] || allowed_columns[default] || default
14+
Arel.sql(sql)
15+
end
16+
1117
def set_cache_headers(browser_ttl: 5.minutes, cdn_ttl: 6.hours)
1218
return unless request.get?
1319
response.headers['Cache-Control'] = "public, max-age=#{browser_ttl.to_i}, s-maxage=#{cdn_ttl.to_i}, stale-while-revalidate=#{cdn_ttl.to_i}, stale-if-error=#{1.day.to_i}"

app/controllers/issues_controller.rb

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,12 @@ def index
77
scope = scope.joins(:project).merge(Project.language(params[:language])) if params[:language].present?
88
scope = scope.joins(:project).merge(Project.keyword(params[:keyword])) if params[:keyword].present?
99

10-
# Define allowed sort fields with database expressions
11-
allowed_sort_fields = {
12-
'created_at' => 'issues.created_at',
13-
'updated_at' => 'issues.updated_at',
14-
'stars' => "CAST(projects.repository->>'stargazers_count' AS INTEGER)"
15-
}
16-
1710
if params[:sort].present? || params[:order].present?
18-
sort_key = params[:sort].presence || 'created_at'
19-
sort_field = allowed_sort_fields[sort_key] || 'issues.created_at'
20-
11+
sort = sanitize_sort(Issue.sortable_columns, default: 'created_at')
2112
if params[:order] == 'asc'
22-
scope = scope.order(Arel.sql(sort_field).asc.nulls_last)
13+
scope = scope.order(sort.asc.nulls_last)
2314
else
24-
scope = scope.order(Arel.sql(sort_field).desc.nulls_last)
15+
scope = scope.order(sort.desc.nulls_last)
2516
end
2617
else
2718
scope = scope.order('issues.created_at DESC')

app/models/issue.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,12 @@
11
class Issue < ApplicationRecord
2+
def self.sortable_columns
3+
{
4+
'created_at' => 'issues.created_at',
5+
'updated_at' => 'issues.updated_at',
6+
'stars' => "CAST(projects.repository->>'stargazers_count' AS INTEGER)",
7+
}
8+
end
9+
210
belongs_to :project
311

412
scope :past_year, -> { where('created_at > ?', 1.year.ago) }

app/models/project.rb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,18 @@
33
class Project < ApplicationRecord
44
include EcosystemApiClient
55

6+
def self.sortable_columns
7+
{
8+
'projects.updated_at' => 'projects.updated_at',
9+
'projects.created_at' => 'projects.created_at',
10+
'updated_at' => 'updated_at',
11+
'created_at' => 'created_at',
12+
'last_synced_at' => 'last_synced_at',
13+
'score' => 'score',
14+
'name' => 'name',
15+
}
16+
end
17+
618
SEARCH_TSVECTOR = <<~SQL.squish
719
to_tsvector('english',
820
coalesce(projects.name, '') || ' ' ||

0 commit comments

Comments
 (0)