CREATE TABLE posts (
id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
author_id bigint NOT NULL REFERENCES authors (id),
title text NOT NULL,
body text NOT NULL,
published_at timestamptz NOT NULL DEFAULT now()
export interface PageInfo {
hasNextPage: boolean;
hasPreviousPage: boolean;
startCursor: string | null;
endCursor: string | null;
}
class Article < ApplicationRecord
scope :ranked, -> { order(score: :desc, id: :desc) }
scope :after_cursor, ->(cursor) do
return all if cursor.nil?
module KeysetPageable
extend ActiveSupport::Concern
included do
scope :keyset_page, ->(cursor: nil, per: 20) do
per = per.to_i.clamp(1, 100)
import base64
import json
from datetime import datetime
from typing import Optional, Tuple
package com.example.feed;
import java.nio.charset.StandardCharsets;
import java.time.Instant;
import java.util.Base64;
export interface Cursor {
createdAt: string;
id: string;
}
export function encodeCursor(c: Cursor): string {
import base64
import json
from datetime import datetime
class InvalidCursor(Exception):
use base64::{engine::general_purpose::URL_SAFE_NO_PAD, Engine};
use serde::{Deserialize, Serialize};
use time::OffsetDateTime;
use uuid::Uuid;
#[derive(Debug, Clone, Serialize, Deserialize)]
module KeysetPaginatable
extend ActiveSupport::Concern
class_methods do
def keyset_page(cursor: nil, limit: 20, direction: :desc)
limit = limit.to_i.clamp(1, 100)
package feed
import (
"encoding/base64"
"encoding/json"
"time"
function encodeCursor(row) {
if (!row) return null;
const payload = JSON.stringify({ t: row.created_at, id: row.id });
return Buffer.from(payload, 'utf8').toString('base64url');
}