diff --git a/spec/model/model_spec.cr b/spec/model/model_spec.cr index 0293c1620..79a3607f5 100644 --- a/spec/model/model_spec.cr +++ b/spec/model/model_spec.cr @@ -328,5 +328,36 @@ module ModelSpec end end end + + context "with pagination" do + it "can pull the next 5 users from page 2" do + temporary do + reinit + + 15.times do |x| + User.create!({first_name: "user#{x}"}) + end + + users = User.query.paginate(page: 2, per_page: 5) + users.map(&.first_name).should eq ["user5", "user6", "user7", "user8", "user9"] + users.total_entries.should eq 15 + end + end + + it "can paginate with where clause" do + temporary do + reinit + last_names = ["smith", "jones"] + 15.times do |x| + last_name = last_names[x % 2]? + User.create!({first_name: "user#{x}", last_name: last_name}) + end + + users = User.query.where { last_name == "smith" }.paginate(page: 1, per_page: 5) + users.map(&.first_name).should eq ["user0", "user2", "user4", "user6", "user8"] + users.total_entries.should eq 8 + end + end + end end end diff --git a/src/clear/sql/query/with_pagination.cr b/src/clear/sql/query/with_pagination.cr index 68e362b8f..5566b055c 100644 --- a/src/clear/sql/query/with_pagination.cr +++ b/src/clear/sql/query/with_pagination.cr @@ -1,9 +1,26 @@ module Clear::SQL::Query::WithPagination + DEFAULT_LIMIT = 50 + DEFAULT_PAGE = 1 macro included property total_entries : Int64? = nil end + # Maybe this goes on the Collection? + def paginate(page : Int32 = DEFAULT_PAGE, per_page : Int32 = DEFAULT_LIMIT) + # Need to clear these values to get total count first + clear_limit.clear_offset + # TODO: this fails. Maybe something with clear_select? + # @total_entries = count + @total_entries = Clear::SQL.connection.scalar("SELECT COUNT(*) #{print_froms} #{print_wheres}").as(Int64) + + # Calculate proper offset and set limit + page = page < 1 ? 1 : page + @limit = per_page.to_i64 + @offset = (per_page * (page - 1)).to_i64 + change! + end + def per_page limit end