Available at: https://bits-and-bites.fly.dev/
This is a fully-dockerized Rails 7 & React web application that helps you not to starve! π€€ You can search for ingredients you have on hand, and BitsAndBites will suggest a myriad of recipes for you to cook using those ingredients.
BitsAndBites was built using:
- Ruby:
3.2.1
- Rails:
7.0.8
- React:
18.2.0
- PostgreSQL:
15.3
- Docker:
20.10.5
& Docker-compose:1.25.0
(and DALLΒ·E 3 for this beautiful logo! π€)
- Introduction
- User Stories
- Prerequisites
- Setup
- Running the application
- Running tests
- Endpoints
- Sample Requests and Responses
- Database Schema
- Project Structure
- Troubleshooting
- Wrapping Up
BitsAndBites comes as a solution to the following challenge:
It's dinner time ! Create an application that helps users find the most relevant recipes that they can prepare with the ingredients that they have at home.
As a user, I want to be able to search for recipes by ingredients, so that I can find recipes that I can cook right now.
As a user, I want to be able to see the list of ingredients for each recipe, so that I can make sure I have all the ingredients I need.
As a user, I just want to browse recipes, so that I can find something that looks delicious. Then I can go out and buy the ingredients I need.
Ensure you have Docker and Docker Compose installed on your machine.
-
To install Docker, follow the instructions here: https://docs.docker.com/engine/install/
-
To install Docker Compose, follow the instructions here: https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-compose-on-ubuntu-20-04#step-1-installing-docker-compose (as it is tested using the
docker-compose
v1. Alternatively, you could try v2 version from here: https://docs.docker.com/compose but I am not sure about thedocker-compose.yml
compatibility)
All the actual application dependencies are handled by Docker. Check Dockerfile
and docker-compose.yml
files for more info on that.
-
Clone the repository:
git clone [email protected]:christospi/bits-and-bites.git
-
Navigate to the application directory:
cd bits-and-bites
-
Environment configuration: The application uses environment variables for configuration. A
.env.sample
file is provided in the repository as a template.-
Copy the
.env.sample
file to create a new.env
file:cp .env.sample .env
-
Open the
.env
file in a text editor and replace the placeholder values with your actual values... OR -
Use mine... π€«π«πͺ
# Database config POSTGRES_DB=bits_and_bites_development POSTGRES_HOST=localhost POSTGRES_USER=ratatouille POSTGRES_PASSWORD=linguine POSTGRES_PORT=5432 # Rails config RAILS_ENV=development RAILS_MASTER_KEY=7202648ae149c3c955cd24439faaf2af
-
-
Build and start the Docker containers:
docker-compose up --build
The database will be prepared automatically during the startup process.
Once the Docker containers are up and running, BitsAndBites will be available at http://localhost:3000
You can import the sample dataset by running the following command:
docker-compose exec web rake recipes:import_small
or import the full dataset by running the following command:
docker-compose exec web rake recipes:import_all
To run the test suite, execute the following command:
docker-compose -f docker-compose.test.yml up --build
This will build and start the Docker containers and run all the rspec
tests.
The API exposes the following endpoints:
-
GET /recipes
: Returns a list of recipes sorted by ratings descending, with the most recent users appearing first. Supports optional parameters for filtering and pagination. Currently supported optional parameters:keyphrase
: A comma separated string of ingredients to search recipes for.page
: The page number to return. Defaults to 1.
For a few samples, check the following section (Sample Requests and Responses).
This section provides examples of how to call the supported endpoints and what kind of responses you can expect.
Request:
curl -X GET http://localhost:3000/api/v1/recipes/index
Response:
This endpoint returns a list of recipes, including ingredients.
The response contains an array of Recipe objects. Each Recipe object includes id
, title
, cookTimeInMinutes
, prepTimeInMinutes
,
ratings
, category
, cuisine
, author
, imageUrl
, and ingredients
attributes.
{
"recipes": [
{
"id": 10011,
"title": "Sloppy Does",
"cookTimeInMinutes": 20,
"prepTimeInMinutes": 10,
"ratings": "5.0",
"category": "Venison Recipes",
"cuisine": "",
"author": "Zacktheperson",
"imageUrl": "https://imagesvc.meredithcorp.io/v3/mm/image?url=https%3A%2F%2Fimages.media-allrecipes.com%2Fuserphotos%2F1578799.jpg",
"ingredients": [
{
"id": 27,
"name": "olive oil",
"quantity": "1 teaspoon"
},
{
"id": 2845,
"name": "ground venison",
"quantity": "1 pound"
}, // ... more ingredients
]
},
// ... more records
],
"meta": {
"totalPages": 100
}
}
You can also use query parameters to filter and paginate the results. Here's an example that fetches the first page of Recipes that include the ingredients "milk" and "sugar":
Request:
curl -X GET "http://localhost:3000/api/v1/recipes/index?keyphrase=milk%2C+sugar&page=1"
This request will return the following response:
{
"recipes": [
{
"id": 7051,
"title": "Homemade Sweetened Condensed Milk",
"cookTimeInMinutes": 10,
"prepTimeInMinutes": 5,
"ratings": "4.21",
"category": "Everyday Cooking",
"cuisine": "",
"author": "lauren11",
"imageUrl": "https://imagesvc.meredithcorp.io/v3/mm/image?url=https%3A%2F%2Fimages.media-allrecipes.com%2Fuserphotos%2F1387465.jpg",
"ingredients": [
{
"id": 3,
"name": "white sugar",
"quantity": "1 Β½ cups"
},
{
"id": 1948,
"name": "can evaporated milk",
"quantity": "1 (12 fluid ounce)"
}
]
}
],
"meta": {
"totalPages": 1
}
}
The database schema is defined in db/schema.rb
file. It contains the following tables:
The project follows a typical Rails application structure with models, controllers, and services.
- Services: Located in
app/services
directory, these files encapsulate business logic related to models, letting us have quite thin models. This includes theRecipeSearchService
class used to search recipes by ingredients. - Serializers: Located in the
app/serializers
directory, these files handle the conversion of data for application models. It containsRecipeSerializer
which is responsible for serializingRecipe
records along with theirIngredients
, in order to be returned by the API (and consumed by the React frontend). - Rake tasks: Located in the
lib/tasks
directory, these files contain the rake tasks for importing recipes from the provided JSON files. It includesimport_recipes.rake
which is responsible for importing recipes from the provided JSON files. - React frontend: Located in the
app/javascript
directory, these files contain the React frontend for the application. Every component is located in its own directory. It includesApp
which is responsible for rendering the application,Home
which is responsible for rendering the home page,Recipes
which is responsible for rendering a list of recipes andRecipeSearch
which is responsible for rendering the search form. - Specs: Test coverage is provided by RSpec. Located in the
spec
directory, these files contain the test suite for our application, including unit tests for models, controller actions and services. - Dockerfile and docker-compose.yml: These files define the Docker configuration for setting up and running the application in a Docker container. It handles both our database (Postgres), Rails app and React.
- .env.sample: Sample configuration files for the required environment variables. Following the instructructions in Setup section, you should create a new local file named
.env
in application root directory with the appropriate values.
If you encounter issues while setting up the application, you may need to rebuild your Docker images:
docker-compose down
docker-compose up --build
You may also need to check the container logs to debug any issues:
docker-compose logs