Beans0063/app-list-api

★ 0Forks 0RubyGitHub ↗Compare

README

App List API

A Rails API that vends a list of apps in JSON format, designed to be consumed by browser-based and iOS clients.

Requirements

  • Ruby 3.3.6
  • Bundler

Getting Started

# Install dependencies
bundle install

# Set up the database
bin/rails db:create db:migrate db:seed

# Start the server
bin/rails server

The API will be available at http://localhost:3000.

Endpoints

All endpoints are namespaced under /v1/.

Method Path Description
GET /v1/apps List all apps (paginated)
GET /v1/apps?q=search Search apps by name or tagline
GET /v1/apps/:id Fetch a single app
GET /up Health check

Example Requests

# List all apps
curl http://localhost:3000/v1/apps

# Search for an app
curl "http://localhost:3000/v1/apps?q=picnic"

# Paginate (page 2, 5 per page)
curl "http://localhost:3000/v1/apps?page=2&per_page=5"

# Fetch a single app
curl http://localhost:3000/v1/apps/1

# Health check
curl http://localhost:3000/up

Search

Search is case-insensitive and matches against both name and tagline fields. Pass the q parameter:

GET /v1/apps?q=picnic

Returns all apps where "picnic" appears anywhere in the name or tagline.

Pagination

The list endpoint returns paginated results by default:

  • page — page number (default: 1, minimum: 1)
  • per_page — results per page (default: 20, maximum: 100)

The meta object in the response includes page, per_page, and total so clients can render pagination controls.

Response Format

Success — list (200)

{
  "apps": [
    {
      "id": 1,
      "name": "Picnic Basket",
      "tagline": "The best way to fill up your picnic basket!",
      "image_url": "https://picsum.photos/seed/picnic-basket/200"
    }
  ],
  "meta": {
    "page": 1,
    "per_page": 20,
    "total": 8
  }
}

Success — single app (200)

{
  "id": 1,
  "name": "Picnic Basket",
  "tagline": "The best way to fill up your picnic basket!",
  "image_url": "https://picsum.photos/seed/picnic-basket/200"
}

Error Responses

All errors return a JSON object with an error key.

Status Meaning Example
400 Invalid parameters (array params, search query too long) { "error": "Invalid parameter: q" }
404 App not found or unmatched route { "error": "App not found" }
500 Unexpected server error { "error": "Internal server error" }
503 Health check failed (DB unreachable) { "error": "Database connection failed" }

Running Tests

bundle exec rspec

Covers request specs for all endpoints (pagination, search, input validation, error handling, health check) and model specs for validations and the search scope.

Linting and Security

# Static security analysis
bundle exec brakeman -q

# Style linting
bundle exec rubocop

CI

GitHub Actions runs on every push to main and on pull requests:

  • Tests — RSpec suite with database setup
  • Security — Brakeman (static analysis) and bundler-audit (gem vulnerabilities)
  • Linting — RuboCop for consistent style

Project Structure

app/
  controllers/
    application_controller.rb      # Global error handling, catch-all 404
    health_controller.rb           # GET /up — DB connectivity check
    v1/
      apps_controller.rb           # GET /v1/apps, GET /v1/apps/:id
  models/
    app.rb                         # Validations, search scope
  serializers/
    app_serializer.rb              # Explicit API response contract (Blueprinter)
db/
  migrate/                         # Schema migrations
  seeds.rb                         # Sample app data
spec/
  models/app_spec.rb               # Model and search specs
  requests/apps_spec.rb            # API endpoint specs
  requests/health_spec.rb          # Health check specs
  factories/apps.rb                # FactoryBot factory

Key Dependencies

Gem Purpose
blueprinter Serializer — explicit API response contract
rspec-rails Test framework
factory_bot_rails Test data factories
shoulda-matchers Concise validation matchers

Notes

See NOTES.md for a full account of architectural decisions, trade-offs, and what would be added with more time.

Issues