Skip to content

Ruby Sinatra Todos

A REST API for managing todos, built with Ruby/Sinatra and PostgreSQL. Demonstrates deploying a database-backed Ruby application on AppMecca.

Overview

Repository git@gitlab.com:appmecca-sample-apps/ruby-sinatra-todos.git
Tech Stack Ruby 3.3 / Sinatra / Sequel / Puma
Services api (port 4567)
Database Yes
Cache None
URL Pattern https://ruby-sinatra-todos-api.{env}.appmecca.net

What This App Demonstrates

  • Deploying a database-backed Ruby application on AppMecca
  • Sequel ORM with auto-migration for schema management
  • Entrypoint script pattern (waiting for database, then starting the app)
  • REST API with full CRUD operations against PostgreSQL
  • The database.enabled: true configuration pattern

appmecca.yaml

containers:
  - name: api
    dockerfile: Dockerfile
    context: .

deploy:
  - name: api
    container: api
    port: 4567
    health_check:
      path: /health

database:
  enabled: true

The only addition compared to Hello Ruby is database.enabled: true. AppMecca provisions a PostgreSQL database on first deploy and injects DATABASE_URL, DB_HOST, DB_PORT, DB_NAME, DB_USER and DB_PASSWORD into every container of the app automatically.

Never hardcode the database name

The database and user names are opaque, generated identifiers of the form am_<hash>_db and am_<hash>_user — derived from the app and branch, so each branch gets its own isolated database. They are never ruby-sinatra-todos_db. Always read DATABASE_URL (or the DB_* pair).

Step-by-Step Deployment

1. Register the app

mecca register git@gitlab.com:appmecca-sample-apps/ruby-sinatra-todos.git -e dev

2. Build the container

mecca build trigger -e dev -g git@gitlab.com:appmecca-sample-apps/ruby-sinatra-todos.git
Expected output
Build started: build-xxxxxxxx
Cloning repository...
Building container: api
Pushing to the image registry: appmecca-dev-ruby-sinatra-todos
Build complete. Duration: 45s

3. Deploy

mecca app deploy -e dev ruby-sinatra-todos
Expected output
Deploying ruby-sinatra-todos to dev...
Deployment queued: deploy-xxxxxxxx
Waiting for agents...
Container started: ruby-sinatra-todos-api
Health check passed: /health -> 200 OK
Deployment complete.

Services:
  api: https://ruby-sinatra-todos-api.dev.appmecca.net

4. Verify

mecca app show -e dev ruby-sinatra-todos

Test the API:

# Health check
curl https://ruby-sinatra-todos-api.dev.appmecca.net/health
{"status": "healthy"}
# Create a todo
curl -X POST https://ruby-sinatra-todos-api.dev.appmecca.net/api/todos \
  -H "Content-Type: application/json" \
  -d '{"title": "Deploy more apps", "done": false}'

# List all todos
curl https://ruby-sinatra-todos-api.dev.appmecca.net/api/todos

# Update a todo
curl -X PUT https://ruby-sinatra-todos-api.dev.appmecca.net/api/todos/1 \
  -H "Content-Type: application/json" \
  -d '{"done": true}'

# Delete a todo
curl -X DELETE https://ruby-sinatra-todos-api.dev.appmecca.net/api/todos/1

API Endpoints

Method Path Description
GET /health Health check
GET /api/todos List all todos
POST /api/todos Create a todo
PUT /api/todos/:id Update a todo
DELETE /api/todos/:id Delete a todo

Key Concepts

Sequel ORM (auto-migration)

Sequel is a lightweight Ruby ORM that supports auto-migration -- defining the schema in Ruby code and having it applied automatically on startup. Unlike Rails ActiveRecord which uses versioned migration files, Sequel's create_table? method creates the table only if it does not already exist. This makes the entrypoint simpler: no separate migration command is needed.

Entrypoint scripts (waiting for DB)

Database-backed apps need an entrypoint script that waits for the database to accept connections before starting the application. The retry loop pattern (attempt connection, sleep, retry) is universal across all languages and frameworks. In Ruby, the script uses PG.connect with the APPMECCA-injected environment variables to test the connection.

Any language, same workflow

AppMecca does not care what language your application is written in. As long as your container listens on the declared port and responds to health checks, the deployment workflow is identical.

What's Next?