Thanks to visit codestin.com
Credit goes to github.com

Skip to content

RESTful API for restaurant management, menus, and menu items, built with Ruby on Rails 8.0.2 following the JSON:API specification.

Notifications You must be signed in to change notification settings

RomuloOliveira94/romin-bites

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

49 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Romin Bites API Documentation

πŸ“‹ Overview

RESTful API for restaurant management, menus, and menu items, built with Ruby on Rails 8.0.2 following the JSON:API specification.

πŸš€ Tech Stack

  • Ruby on Rails 8.0.2
  • SQLite3 (Database)
  • JSON:API Serializer (Response formatting)
  • Puma (Web server)
  • RSpec (Testing framework)
  • GitHub Actions (CI/CD)

πŸ“¦ Installation

Prerequisites

  • Ruby 3.x
  • Bundler
  • SQLite3

Setup

# Clone the repository
git clone <repository-url>
cd romin-bites

# Install dependencies
bundle install

# Setup database
rails db:create
rails db:migrate
rails db:seed

# Run the server
rails server

πŸ“‘ API Endpoints

Base URL

https://rominbites.romin.dev.br/api/v1

Authentication

Currently, the API does not require authentication (public access).


πŸͺ Restaurants

List all restaurants

GET /api/v1/restaurants

cURL Example:

curl -X GET "https://rominbites.romin.dev.br/api/v1/restaurants" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json"

Response:

{
  "data": [
    {
      "id": "1",
      "type": "restaurant",
      "attributes": {
        "name": "Bella Italia",
        "description": "Authentic Italian cuisine",
        "created_at": "2025-08-25T10:00:00.000Z",
        "updated_at": "2025-08-25T10:00:00.000Z"
      },
      "relationships": {
        "menus": {
          "data": []
        }
      }
    }
  ]
}

Get a specific restaurant

GET /api/v1/restaurants/:id

cURL Example:

curl -X GET "https://rominbites.romin.dev.br/api/v1/restaurants/1" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json"

Include menus with restaurant

GET /api/v1/restaurants/:id?include=menus

cURL Example:

curl -X GET "https://rominbites.romin.dev.br/api/v1/restaurants/1?include=menus" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json"

Response with includes:

{
  "data": {
    "id": "1",
    "type": "restaurant",
    "attributes": {
      "name": "Bella Italia",
      "description": "Authentic Italian cuisine",
      "created_at": "2025-08-25T10:00:00.000Z",
      "updated_at": "2025-08-25T10:00:00.000Z"
    },
    "relationships": {
      "menus": {
        "data": [
          {
            "id": "1",
            "type": "menu"
          }
        ]
      }
    }
  },
  "included": [
    {
      "id": "1",
      "type": "menu",
      "attributes": {
        "name": "Lunch Menu",
        "description": "Available from 12:00 to 15:00",
        "created_at": "2025-08-25T10:00:00.000Z",
        "updated_at": "2025-08-25T10:00:00.000Z"
      },
      "relationships": {
        "menu_items": {
          "data": []
        }
      }
    }
  ]
}

Include nested menu items

GET /api/v1/restaurants/:id?include=menus.menu_items

cURL Example:

curl -X GET "https://rominbites.romin.dev.br/api/v1/restaurants/1?include=menus.menu_items" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json"

Import restaurants from file

POST /api/v1/restaurants/import

cURL Example:

curl -X POST "https://rominbites.romin.dev.br/api/v1/restaurants/import" \
  -H "Accept: application/json" \
  -F "[email protected]"

Response:

{
  "success": true,
  "message": "Import queued for processing",
  "job_id": "12345-67890-abcdef",
  "status_url": "https://rominbites.romin.dev.br/api/v1/restaurants/import_status?job_id=12345-67890-abcdef"
}

Check import status

GET /api/v1/restaurants/import_status?job_id=:job_id

cURL Example:

curl -X GET "https://rominbites.romin.dev.br/api/v1/restaurants/import_status?job_id=12345-67890-abcdef" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json"

Response (Processing):

{
  "success": false,
  "message": "Still processing",
  "job_id": "12345-67890-abcdef"
}

Response (Completed - Success):

{
  "success": true,
  "message": "Import completed successfully",
  "logs": {
    "restaurants": {
      "success": [
        "Restaurant 'Bella Italia' created with ID: 1",
        "Restaurant 'Pizza Palace' found with ID: 2"
      ],
      "error": []
    },
    "menus": {
      "success": [
        "Menu 'Lunch Menu' created for restaurant Bella Italia with ID: 1",
        "Menu 'Dinner Menu' created for restaurant Bella Italia with ID: 2"
      ],
      "error": []
    },
    "menu_items": {
      "success": [
        "Menu item 'Margherita Pizza' created with price: 12.99 and ID: 1",
        "Menu item 'Caesar Salad' found with ID: 2"
      ],
      "error": []
    },
    "associations": {
      "success": [
        "Association created between 'Margherita Pizza' and 'Lunch Menu'",
        "Association created between 'Caesar Salad' and 'Lunch Menu'"
      ],
      "error": []
    }
  },
  "stats": {
    "restaurants_created": 1,
    "restaurants_found": 1,
    "menus_created": 2,
    "menus_found": 0,
    "menu_items_created": 1,
    "menu_items_found": 1,
    "associations_created": 2
  }
}

Response (Completed - With Errors):

{
  "success": false,
  "message": "Import completed with errors",
  "logs": {
    "restaurants": {
      "success": [
        "Restaurant 'Bella Italia' created with ID: 1"
      ],
      "error": [
        "Error creating restaurant 'Invalid Restaurant': Name can't be blank"
      ]
    },
    "menus": {
      "success": [
        "Menu 'Lunch Menu' created for restaurant Bella Italia with ID: 1"
      ],
      "error": [
        "Error in menu 'Invalid Menu' for restaurant Bella Italia: Name can't be blank"
      ]
    },
    "menu_items": {
      "success": [
        "Menu item 'Margherita Pizza' created with price: 12.99 and ID: 1"
      ],
      "error": [
        "Error creating menu item 'Invalid Item': Price must be greater than or equal to 0"
      ]
    },
    "associations": {
      "success": [
        "Association created between 'Margherita Pizza' and 'Lunch Menu'"
      ],
      "error": []
    }
  },
  "stats": {
    "restaurants_created": 1,
    "restaurants_found": 0,
    "menus_created": 1,
    "menus_found": 0,
    "menu_items_created": 1,
    "menu_items_found": 0,
    "associations_created": 1
  }
}

Response (Failed):

{
  "success": false,
  "message": "Import failed: Invalid JSON format",
  "errors": ["Invalid JSON format"],
  "logs": [],
  "stats": {}
}

🍽️ Menus

List all menus

GET /api/v1/menus

cURL Example:

curl -X GET "https://rominbites.romin.dev.br/api/v1/menus" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json"

List menus for a specific restaurant

GET /api/v1/restaurants/:restaurant_id/menus

cURL Example:

curl -X GET "https://rominbites.romin.dev.br/api/v1/restaurants/1/menus" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json"

Response:

{
  "data": [
    {
      "id": "1",
      "type": "menu",
      "attributes": {
        "name": "Lunch Menu",
        "description": "Available from 12:00 to 15:00",
        "created_at": "2025-08-25T10:00:00.000Z",
        "updated_at": "2025-08-25T10:00:00.000Z"
      },
      "relationships": {
        "menu_items": {
          "data": []
        }
      }
    }
  ]
}

Get a specific menu

GET /api/v1/menus/:id

cURL Example:

curl -X GET "https://rominbites.romin.dev.br/api/v1/menus/1" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json"

Include menu items with menu

GET /api/v1/menus/:id?include=menu_items

cURL Example:

curl -X GET "https://rominbites.romin.dev.br/api/v1/menus/1?include=menu_items" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json"

Response with includes:

{
  "data": {
    "id": "1",
    "type": "menu",
    "attributes": {
      "name": "Lunch Menu",
      "description": "Available from 12:00 to 15:00",
      "created_at": "2025-08-25T10:00:00.000Z",
      "updated_at": "2025-08-25T10:00:00.000Z"
    },
    "relationships": {
      "menu_items": {
        "data": [
          {
            "id": "1",
            "type": "menu_item"
          }
        ]
      }
    }
  },
  "included": [
    {
      "id": "1",
      "type": "menu_item",
      "attributes": {
        "name": "Margherita Pizza",
        "description": "Fresh tomatoes, mozzarella, basil",
        "price": "12.99",
        "created_at": "2025-08-25T10:00:00.000Z",
        "updated_at": "2025-08-25T10:00:00.000Z"
      },
      "relationships": {
        "menus": {
          "data": []
        }
      }
    }
  ]
}

πŸ• Menu Items

List all menu items

GET /api/v1/menu_items

cURL Example:

curl -X GET "https://rominbites.romin.dev.br/api/v1/menu_items" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json"

List menu items for a specific menu

GET /api/v1/menus/:menu_id/menu_items

cURL Example:

curl -X GET "https://rominbites.romin.dev.br/api/v1/menus/1/menu_items" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json"

Response:

{
  "data": [
    {
      "id": "1",
      "type": "menu_item",
      "attributes": {
        "name": "Margherita Pizza",
        "description": "Fresh tomatoes, mozzarella, basil",
        "price": "12.99",
        "created_at": "2025-08-25T10:00:00.000Z",
        "updated_at": "2025-08-25T10:00:00.000Z"
      },
      "relationships": {
        "menus": {
          "data": []
        }
      }
    }
  ]
}

Get a specific menu item

GET /api/v1/menu_items/:id

cURL Example:

curl -X GET "https://rominbites.romin.dev.br/api/v1/menu_items/1" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json"

Include menus with menu item

GET /api/v1/menu_items/:id?include=menus

cURL Example:

curl -X GET "https://rominbites.romin.dev.br/api/v1/menu_items/1?include=menus" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json"

Response with includes:

{
  "data": {
    "id": "1",
    "type": "menu_item",
    "attributes": {
      "name": "Margherita Pizza",
      "description": "Fresh tomatoes, mozzarella, basil",
      "price": "12.99",
      "created_at": "2025-08-25T10:00:00.000Z",
      "updated_at": "2025-08-25T10:00:00.000Z"
    },
    "relationships": {
      "menus": {
        "data": [
          {
            "id": "1",
            "type": "menu"
          }
        ]
      }
    }
  },
  "included": [
    {
      "id": "1",
      "type": "menu",
      "attributes": {
        "name": "Lunch Menu",
        "description": "Available from 12:00 to 15:00",
        "created_at": "2025-08-25T10:00:00.000Z",
        "updated_at": "2025-08-25T10:00:00.000Z"
      },
      "relationships": {
        "menu_items": {
          "data": []
        }
      }
    }
  ]
}

πŸ“Š Response Format

All responses follow the JSON:API specification:

Success Response Structure

{
  "data": {
    "id": "1",
    "type": "resource_type",
    "attributes": {
      // resource attributes
    },
    "relationships": {
      // resource relationships
    }
  },
  "included": [
    // related resources when using include parameter
  ]
}

Error Response Structure

{
  "error": "Error message"
}

πŸ” Query Parameters

Include Related Resources

You can include related resources using the include parameter:

  • ?include=menus - Include menus (for restaurants)
  • ?include=menu_items - Include menu items (for menus)
  • ?include=menus.menu_items - Include nested relationships (menus with their menu items)

Examples:

# Get restaurant with its menus
curl "https://rominbites.romin.dev.br/api/v1/restaurants/1?include=menus"

# Get restaurant with menus and their items
curl "https://rominbites.romin.dev.br/api/v1/restaurants/1?include=menus.menu_items"

# Get menu with its items
curl "https://rominbites.romin.dev.br/api/v1/menus/1?include=menu_items"

# Get menu item with its menus
curl "https://rominbites.romin.dev.br/api/v1/menu_items/1?include=menus"

πŸ“ Model Attributes

Restaurant

  • id (integer) - Unique identifier
  • name (string, required) - Restaurant name
  • description (text, optional) - Restaurant description
  • created_at (datetime) - Creation timestamp
  • updated_at (datetime) - Last update timestamp

Menu

  • id (integer) - Unique identifier
  • name (string, required) - Menu name
  • description (text, optional) - Menu description
  • restaurant_id (integer, required) - Reference to restaurant
  • created_at (datetime) - Creation timestamp
  • updated_at (datetime) - Last update timestamp

MenuItem

  • id (integer) - Unique identifier
  • name (string, required, unique) - Menu item name
  • description (text, optional) - Item description
  • price (decimal, required, >= 0) - Item price with 2 decimal places
  • created_at (datetime) - Creation timestamp
  • updated_at (datetime) - Last update timestamp

πŸ”„ Relationships

  • Restaurant has many Menus (one-to-many)
  • Menu belongs to Restaurant (many-to-one)
  • Menu has many MenuItems (many-to-many through join table)
  • MenuItem has many Menus (many-to-many through join table)

⚑ HTTP Status Codes

  • 200 OK - Successful GET request
  • 202 Accepted - Import job queued or still processing
  • 404 Not Found - Resource not found
  • 422 Unprocessable Content - Missing required parameters
  • 500 Internal Server Error - Server error during import

πŸ› οΈ Development

Running Tests

# Run all tests
bundle exec rspec

# Run specific test file
bundle exec rspec spec/requests/api/v1/restaurants_spec.rb

# Run with documentation format
bundle exec rspec --format documentation

Code Quality

# Security analysis
bundle exec brakeman

# Code style
bundle exec rubocop

# N+1 query detection (in development)
# Bullet gem is configured to detect N+1 queries

πŸ“„ License

This project is open source and available under the MIT License.


Note: This API follows RESTful conventions and JSON:API specification. All timestamps are in ISO 8601 format (UTC).

About

RESTful API for restaurant management, menus, and menu items, built with Ruby on Rails 8.0.2 following the JSON:API specification.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published