Repository navigation
Add Ruby Sinatra PostgreSQL quickstart application #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
a9748a5
8369411
1d71994
f663767
cff397a
b1ddf36
5c9f135
0a3c42b
927de96
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| # Git history | ||
| .git/ | ||
| .gitignore | ||
|
|
||
| # Keploy recorded test sets (generated at runtime, not needed in image) | ||
| keploy/ | ||
|
|
||
| # Local environment secrets — never bake into a shared image | ||
| .env | ||
| .env.* | ||
|
|
||
| # Dev tooling | ||
| run-keploy.sh | ||
|
|
||
| # Docker files themselves | ||
| .dockerignore | ||
| docker-compose.yml.test |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| .env | ||
| keploy/ | ||
| *.gem | ||
| *.rbc | ||
| /.config | ||
| /coverage/ | ||
| /InstalledFiles | ||
| /pkg/ | ||
| /spec/reports/ | ||
| /test/tmp/ | ||
| /test/version_tmp/ | ||
| /tmp/ | ||
| .byebug_history | ||
| .dat* | ||
| .repl_history | ||
| .DS_Store | ||
| .env.example | ||
| VALIDATION.md | ||
| 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 --frozen | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
|
||||||
| # Copy application code | ||||||
| COPY . . | ||||||
|
Nsanjayboruds marked this conversation as resolved.
|
||||||
|
|
||||||
| # Expose port | ||||||
| EXPOSE 8000 | ||||||
|
|
||||||
| # Start the application | ||||||
| CMD ["bundle", "exec", "puma", "config.ru", "-p", "8000", "-e", "production"] | ||||||
| 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' |
| 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 |
| 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 | ||
|
|
||
| ``` | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The project layout leaves out |
||
| . | ||
| ├── app.rb | ||
| ├── docker-compose.yml | ||
| ├── init.sql | ||
| ├── run-keploy.sh | ||
| ├── keploy.yml | ||
| └── README.md | ||
| ``` | ||
|
|
||
| ## Run Locally (Optional) | ||
|
|
||
| ```bash | ||
| bundle install | ||
| createdb booksdb | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same Postgres role problem that was fixed in the docs PR is still here: |
||
| psql -d booksdb -f init.sql | ||
| bundle exec ruby app.rb | ||
| ``` | ||
|
|
||
| Health check: | ||
|
|
||
| ```bash | ||
| curl http://localhost:${PORT:-8000}/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 | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This replay command differs from the one in the docs and the one |
||
| ``` | ||
|
|
||
| ## 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 | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Still wrong. The Copilot comment on this line got an unrelated "Switched the command type" reply, and the text didn't change. With the Docker setup Postgres isn't published to the host at all, and the app is on |
||
|
|
||
| ## Notes | ||
|
|
||
| - This quickstart is intentionally API-focused for Keploy record/replay workflows. | ||
| - For deterministic recordings, prefer running the scripted flow instead of manual calls. | ||
Uh oh!
There was an error while loading. Please reload this page.