Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions sinatra-postgres-quickstart/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
.env
keploy/
*.gem
*.rbc
/.config
/coverage/
/InstalledFiles
Comment thread
Nsanjayboruds marked this conversation as resolved.
/pkg/
/spec/reports/
/test/tmp/
/test/version_tmp/
/tmp/
.byebug_history
.dat*
.repl_history
.DS_Store
.env.example
VALIDATION.md
23 changes: 23 additions & 0 deletions sinatra-postgres-quickstart/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
FROM ruby:3.2-slim

WORKDIR /app

# Install system dependencies
RUN apt-get update -qq && \
apt-get install -y --no-install-recommends \
build-essential \
libpq-dev && \
rm -rf /var/lib/apt/lists/*

# Copy Gemfile and install dependencies
COPY Gemfile* ./
RUN bundle install

# Copy application code
COPY . .

# Expose port
EXPOSE 8000

# Start the application
CMD ["bundle", "exec", "puma", "config.ru", "-p", "8000", "-e", "production"]
9 changes: 9 additions & 0 deletions sinatra-postgres-quickstart/Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
source 'https://rubygems.org'

ruby '~> 3.2'

gem 'sinatra', '~> 3.0'
gem 'sinatra-contrib', '~> 3.0'
gem 'pg', '~> 1.5'
gem 'puma', '~> 6.4'
gem 'json', '~> 2.7'
43 changes: 43 additions & 0 deletions sinatra-postgres-quickstart/Gemfile.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
GEM
remote: https://rubygems.org/
specs:
base64 (0.3.0)
json (2.7.1)
multi_json (1.21.1)
mustermann (3.1.1)
nio4r (2.5.9)
pg (1.5.4)
puma (6.4.0)
nio4r (~> 2.0)
rack (2.2.23)
rack-protection (3.2.0)
base64 (>= 0.1.0)
rack (~> 2.2, >= 2.2.4)
sinatra (3.2.0)
mustermann (~> 3.0)
rack (~> 2.2, >= 2.2.4)
rack-protection (= 3.2.0)
tilt (~> 2.0)
sinatra-contrib (3.2.0)
multi_json (>= 0.0.2)
mustermann (~> 3.0)
rack-protection (= 3.2.0)
sinatra (= 3.2.0)
tilt (~> 2.0)
tilt (2.8.0)

PLATFORMS
ruby

DEPENDENCIES
json (~> 2.7)
pg (~> 1.5)
puma (~> 6.4)
sinatra (~> 3.0)
sinatra-contrib (~> 3.0)

RUBY VERSION
ruby 3.2.0

BUNDLED WITH
2.4.20
205 changes: 205 additions & 0 deletions sinatra-postgres-quickstart/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
# Ruby + PostgreSQL API Quickstart for Keploy

This quickstart demonstrates a realistic API testing workflow with Ruby (Sinatra), PostgreSQL, and Keploy.

It goes beyond basic CRUD by including:

- Search, filtering, sorting, and pagination query patterns
- Related resources (`books` and dependent `reviews`)
- Analytics endpoint with aggregates
- Positive and negative test paths in one recording run
- Automated 20-request traffic generation script for repeatable recordings

## Prerequisites

- Docker 20.10+
- Docker Compose v2+
- Keploy CLI installed
- Linux/WSL2 (required by Keploy)

Optional local run (without Docker):

- Ruby 3.2+
- Bundler
- PostgreSQL 15+

## Project Layout

```
.
├── app.rb
├── docker-compose.yml
├── init.sql
├── run-keploy.sh
├── keploy.yml
└── README.md
```

## Run Locally (Optional)

```bash
bundle install
createdb booksdb
psql -d booksdb -f init.sql
bundle exec ruby app.rb
```

Health check:

```bash
curl http://localhost:${APP_HOST_PORT:-18080}/health
```

## Run with Docker (Recommended)

```bash
docker compose up --build
```

Then verify:

```bash
curl http://localhost:${APP_HOST_PORT:-18080}/health
```

Stop services:

```bash
docker compose down
```

If you changed schema and need a clean DB:

```bash
docker compose down -v
```

## Keploy Recording (Automated 20-call Scenario)

Run the script:

```bash
./run-keploy.sh
```

What this script does:

1. Starts Keploy record mode with `docker compose up --build`
2. Selects a free host port in the `18080-18120` range unless `APP_HOST_PORT` is set
3. Waits for `/health`
4. Sends 20 API calls across list/search/filter/create/update/delete/reviews/analytics
5. Includes expected validation and not-found errors (400/404) to capture negative scenarios
6. Stops recording cleanly

Recorded tests are stored in the `keploy/tests` directory.

## Keploy Replay

```bash
keploy test -c "docker compose up" --container-name "ruby-books-app" --cmd-type docker-compose
```

## API Endpoints

### Health

- `GET /health`

### Books

- `GET /books`
- `GET /books/:id`
- `POST /books`
- `PUT /books/:id`
- `PATCH /books/:id`
- `DELETE /books/:id`

Supported query params for `GET /books`:

- `q` (search in title/author)
- `author` (author filter)
- `min_year`, `max_year`
- `sort_by`: `id`, `title`, `author`, `published_year`, `created_at`
- `order`: `asc`, `desc`
- `page` (default: 1)
- `per_page` (default: 10, max: 50)
- `include_stats` (default: true)

For `GET /books/:id`:

- `include_reviews=true` to include dependent reviews in response

### Reviews (Dependent Resource)

- `GET /books/:id/reviews`
- `POST /books/:id/reviews`
- `PATCH /books/:book_id/reviews/:review_id`
- `DELETE /books/:book_id/reviews/:review_id`

### Analytics

- `GET /analytics/books/top-rated`

Supported query params:

- `limit` (default: 5, max: 25)
- `min_reviews` (default: 1, max: 50)

## Example Requests

Search/filter/pagination:

```bash
curl "http://localhost:${APP_HOST_PORT:-18080}/books?q=the&min_year=1900&page=1&per_page=5&sort_by=title&order=asc"
```

Create a book:

```bash
curl -X POST http://localhost:${APP_HOST_PORT:-18080}/books \
-H "Content-Type: application/json" \
-d '{
"title": "Dune",
"author": "Frank Herbert",
"isbn": "9780441013593",
"published_year": 1965
}'
```

Add a review:

```bash
curl -X POST http://localhost:${APP_HOST_PORT:-18080}/books/1/reviews \
-H "Content-Type: application/json" \
-d '{
"reviewer": "qa-team@example.com",
"rating": 5,
"comment": "Excellent world building."
}'
```

Analytics:

```bash
curl "http://localhost:${APP_HOST_PORT:-18080}/analytics/books/top-rated?limit=3&min_reviews=1"
```

## Troubleshooting

1. Keploy record fails to attach:

- Make sure you are on Linux/WSL2
- Ensure container name is `ruby-books-app`

2. Database schema looks stale:

- Run `docker compose down -v` and restart

3. Port conflicts:

- Ensure ports 5432 and 8000 are free

## Notes

- This quickstart is intentionally API-focused for Keploy record/replay workflows.
- For deterministic recordings, prefer running the scripted flow instead of manual calls.
Loading