Recipe Finder is an advanced recipe search application that allows users to discover new recipes based on various criteria. Whether you're hunting for a dish by a specific author, looking for meals within a category, or just trying to find what you can make with chocolate, Recipe Finder has got you covered!
-
Advanced Search: Filter recipes by:
- Author: Discover dishes from your favorite chefs.
- Category: In the mood for a dessert or a main course? We got you!
- Cuisine: Travel the world with your taste buds. From Italian to Japanese cuisine, we have it all.
- Ingredients: Enter what you have, and we'll tell you what you can make!
-
Sorting & Pagination: With a vast database, Recipe Finder offers:
- Sorting: Rank recipes by ratings, preparation time, cooking time, and more.
- Pagination: Efficiently browse through results, 10 recipes at a time.
-
Responsive UI: Designed to be user-friendly and accessible across devices.
- Ruby version:
3.2.1
- Rails version:
7.0.7.2
- PostgreSQL:
14.9
-
Clone the repository:
git clone [email protected]:brunomiguelpinto/recipes.git
-
Navigate to the project directory:
cd pennylane_recipes
-
Install the required gems:
bundle install
-
Set up the database:
rails db:create db:migrate rake recipes:import
-
Start the Rails server:
# Light the stove! 🔥 rails s
-
Access the application by navigating to
http://localhost:3000/recipes/search
in your browser.
The recipes:import
rake task facilitates the importing of recipes from a JSON file into the database. It reads the specified JSON file and iterates over each recipe to create an entry in the database.
To execute the rake task:
rake recipes:import[file_path]
Where file_path
is the path to your JSON file. If not provided, it defaults to lib/recipes-en.json
.
The current implementation of the rake task has some areas of inefficiency:
-
Memory Usage: The entire JSON file is read into memory, which can be problematic for very large files, leading to potential memory issues.
-
Database Operations: For each recipe, the task checks for the existence of its associated
Author
,Category
, andCuisine
individually and then creates them if they don't exist. This results in a lot of individual database reads and writes which can slow down the process. Ideally, these operations should be batched to minimize the number of database interactions. -
Bulk Inserts: Instead of saving each recipe individually, using a method to bulk insert the recipes would improve the performance. Rails provides methods like
insert_all
which can be utilized for such cases.
It's recommended to enhance this task by implementing a streaming mechanism for reading large JSON files and batching the database operations where possible.
The RecipeSearchService
is an integral component of the recipe application, ensuring that users can search for recipes based on various criteria such as author, category, cuisine, and ingredients. Moreover, it provides the capability to sort and paginate the results to ensure a seamless user experience.
-
Robust Filtering:
- The service efficiently filters recipes based on:
- Author: Using the
author_id
. - Category: Using the
category_id
. - Cuisine: Using the
cuisine_id
. - Ingredients: Leverages PostgreSQL's full-text search for ingredient filtering.
- Author: Using the
- The service efficiently filters recipes based on:
-
Sorting:
- Users can sort the results based on valid fields, currently including
ratings
,prep_time
, andcook_time
. - Sorting can be ascending or descending.
- Users can sort the results based on valid fields, currently including
-
Pagination:
- To ensure optimal performance and user experience, the service paginates the results.
- By default, it returns 10 recipes per page, but this can be adjusted.
-
Flexible Integration:
- Designed as a service object, it can be easily integrated into controllers or other services within the application.
To initiate a search, simply call the service like so:
recipes = RecipeSearchService.call(params)
Where params
is a hash containing the search and pagination parameters.
This view provides the functionality to search for recipes based on different criteria such as category, author, cuisine, and ingredients. Once a search is performed, the results are listed below the search form.
The search form uses Rails' form helpers to create various dropdowns and text fields for users to specify their search criteria:
- Category: A dropdown to filter by recipe categories.
- Author: A dropdown to filter by the author of the recipes.
- Cuisine: A dropdown to filter by cuisines.
- Ingredients: A text field where users can input specific ingredients they're looking for in a recipe.
After a search is executed, the results are displayed in a list format. Each recipe item displays:
- The title of the recipe.
- Author, Category, and Cuisine associated with the recipe.
- Cook time and prep time.
- A list of ingredients.
- An image of the recipe (if available).
-
API Integration:
- While the current implementation relies on server-side rendering, this could be enhanced by making calls to an API and rendering the data on the client side. A frontend framework like React would be apt for such an implementation, allowing for more dynamic interactions and improved performance.
-
Data Loading:
- Currently, all categories, authors, and cuisines are preloaded in the dropdowns. This approach is not scalable and can result in performance issues as the data grows. Instead, consider using a select box with search and suggestions (e.g., using libraries like Select2 or react-select). This minimizes the amount of data transferred between layers and offers a more user-friendly search experience.