module Clear::SQL::Query::WithPagination DEFAULT_LIMIT = 50 DEFAULT_PAGE = 1 macro included property total_entries : Int64? = nil end # Enter pagination mode. # This is helpful to manage paginated table. # Pagination will handle the page progression automatically and update # `offset` and `limit` parameters by his own. # # ```crystal # page = query.paginate(2, 50) # ``` def paginate(page : Int32 = DEFAULT_PAGE, per_page : Int32 = DEFAULT_LIMIT) clear_limit.clear_offset @total_entries = count page = {1, page}.max @limit = per_page.to_i64 @offset = (per_page * (page - 1)).to_i64 change! end # Return the number of items maximum per page. def per_page limit end # Return the current page def current_page if offset.nil? || limit.nil? 1 else (offset.as(Int64) / limit.as(Int64)) + 1 end end # Return the total number of pages. def total_pages if limit.nil? || total_entries.nil? 1 else (total_entries.as(Int64) / limit.as(Int64).to_f).ceil.to_i end end # Return `current_page - 1` or `nil` if there is no previous page def previous_page current_page > 1 ? (current_page - 1) : nil end # Return `current_page + 1` or `nil` if there is no next page def next_page current_page < total_pages ? (current_page + 1) : nil end def last_page? next_page.nil? end def first_page? current_page <= 1 end # Helper method that is true when someone tries to fetch a page with a # larger number than the last page. Can be used in combination with flashes # and redirecting. def out_of_bounds? current_page > total_pages end end