Skip to content

Instantly share code, notes, and snippets.

@prsanjay
Created June 8, 2025 17:34
Show Gist options
  • Save prsanjay/377abec9f606d4188e56ffcddc5cd2d9 to your computer and use it in GitHub Desktop.
Save prsanjay/377abec9f606d4188e56ffcddc5cd2d9 to your computer and use it in GitHub Desktop.
Implementing Sorting, Searching and pagination In ROR app
class PostList
SEARCH_COLUMNS = [
'documents.original_document_name',
'users.name',
'languages.name',
'post_statuses.label'
].freeze
ALLOWED_SORT_COLUMNS = {
'title' => 'title',
'username' => 'users.name',
'language_name' => 'languages.name',
'status_label' => 'post_statuses.label',
'created_at' => 'posts.created_at'
}.freeze
ALLOWED_SORT_DIRECTIONS = %w[asc desc].freeze
attr_reader :search, :sort_column, :sort_direction, :page, :per_page
def initialize(serach, sort_column, sort_direction, page, per_page)
@serach = serach
@sort_column = sort_column
@sort_direction = sort_direction
@page = page
@per_page = per_page
end
def call
result = all_data
result = apply_sorting(result)
result, search_result = apply_searching(result)
result = apply_pagination(result)
{
data: result,
current_page: result.current_page,
objects_on_page: result.size,
total_pages: result.total_pages,
total_count: all_data.size
search_count: search_result.size
}
end
private
def all_data
@all_data ||= post_list_query
end
def post_list_query
Post.select("title, created_at, documents.original_document_name, users.name AS username, post_statuses.labe AS post_status_label, languages.name AS language_name")
.joins(:documents, :user, :post_status, :language)
end
def apply_sorting(result)
sort_column = sort_column.presence || 'created_at'
sort_column = ALLOWED_SORT_COLUMNS[sort_column] || ALLOWED_SORT_COLUMNS['created_at']
sort_direction = sort_direction.presence || 'desc'
sort_direction = ALLOWED_SORT_DIRECTIONS.include?(sort_direction.downcase) ? sort_direction : 'desc'
result.order("#{sort_column} #{sort_direction}")
end
def apply_searching(result)
return result if search.blank?
search_pattern = "%#{search}%"
conditions = SEARCH_COLUMNS.map { |col| "#{col} ILIKE :search" }.join(' OR ')
result.where(conditions, search: search_pattern)
end
# Using Kaminari gem
def apply_pagination(result)
result.page(page).per(per_page)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment