This repository hosts a Tea Subscription Service, a backend Rails API project that was given as a take-home challenge. It provides a platform to manage customers, their tea subscriptions, and features various endpoints for interaction.
The Tea Subscription Service is designed to provide a seamless and hassle-free experience to tea enthusiasts who wish to subscribe to their favourite tea offerings. Users can easily subscribe or cancel their subscriptions, and view all their active and cancelled subscriptions at any point. To maintain a scalable and easily consumable API, the service is built with RESTful conventions and Object-Oriented Programming principles.
- Ruby on Rails 7: The framework used for implementing the server-side logic and RESTful API endpoints.
- PostgreSQL: The database system used for data persistence.
- RSpec: The testing framework used for developing the application using Test-Driven Development (TDD) principles.
- jsonapi-serializer: Used for serializing the API data to JSON:API format, providing a clear and organized structure of the data.
- Postman: Used for manual testing of the API endpoints.
-
Clone the Repository: Get started by cloning the repository to your local machine.
-
Install Dependencies: Navigate into the cloned repository and install necessary dependencies:
bundle install
Then create and migrate the database:
rails db:{create, migrate, seed}
If you would like run the
RSpec
test suite, run this command:bundle exec rails rspec
-
Start the Server: Fire up the localhost server.
rails server
Note: Please ensure you have Ruby and Rails installed on your machine before running these commands.
The design of this application's database is structured around four primary tables: customers
, subscriptions
, teas
, and the subscription_teas
join table.
-
Customers: The
customers
table stores information related to our users, including first and last name, email, and address. -
Subscriptions: The
subscriptions
table represents the different subscriptions available. It contains details like title, price, status (active or cancelled), and frequency. It also includes acustomer_id
foreign key to denote the customer to whom each subscription belongs. -
Teas: The
teas
table holds information about the different types of tea available, such as title, description, brewing temperature, and brew time. -
Subscription_Teas: The
subscription_teas
table is a join table that connectssubscriptions
andteas
in a many-to-many relationship. Each row in this table represents a specific tea included in a particular subscription.
In the current design, there is a one-to-many relationship from customers
to subscriptions
, meaning one customer can have multiple subscriptions, but each subscription is associated with only one customer. This was a conscious design decision based on the requirements of the project.
However, it's worth noting that depending on business needs, this design could be revised to a many-to-many relationship between customers
and subscriptions
. This adjustment could allow a subscription
to be shared among multiple customers
. For instance, a family or a group of friends might want to subscribe to the same tea subscription service, each with their own customer account, to track their individual preferences and consumption, but not to pay multiple times for essentially the same subscription being sent to the same address. With the current design, this scenario isn't possible without creating a duplicate subscription
for each customer
. A many-to-many relationship could be established with an additional join table, such as customer_subscriptions
, which would contain customer_id
and subscription_id
to handle shared subscriptions
. These decisions would be based on a thorough understanding of the business model and user requirements, and would need careful handling of the business logic, such as payments, to ensure that shared subscriptions are billed correctly and only once.
Base url to reach the endpoints listed below:
http://localhost:3000/api/v1
All Endpoints
POST /customers/:id/subscriptions
Details
Request:
{
"subscription": {
"title": "Monthly Tea Subscription",
"price": 15.99,
"status": "active",
"frequency": "monthly",
"tea_ids": [1]
}
}
Code | Description |
---|---|
201 | Created |
Response:
{
"data": {
"id": "4",
"type": "subscription",
"attributes": {
"id": 4,
"title": "Monthly Tea Subscription",
"price": "15.99",
"status": "active",
"frequency": "monthly",
"customer_id": 1,
"tea_ids": [
1
]
}
}
}
Code | Description |
---|---|
404 | NOT FOUND |
Response:
{
"error": [
"title": "NOT FOUND",
"status": "404"
]
}
PUT /customers/:id/subscriptions/:id
Details
Request:
{
"subscription": {
"status": "cancelled"
}
}
Code | Description |
---|---|
204 | OK |
Response:
{
"data": {
"id": "1",
"type": "subscription",
"attributes": {
"id": 1,
"title": "Monthly Tea Subscription",
"price": "15.99",
"status": "cancelled",
"frequency": "monthly",
"customer_id": 1,
"tea_ids": [
1,
2
]
}
}
}
Code | Description |
---|---|
404 | NOT FOUND |
Response:
{
"error": [
"title": "NOT FOUND",
"status": "404"
]
}
GET /customers/:id/subscriptions
Details
Request:
"customer_id": 1
Code | Description |
---|---|
200 | OK |
Response:
{
"data": [
{
"id": "1",
"type": "subscription",
"attributes": {
"id": 1,
"title": "Monthly Tea Subscription",
"price": "15.99",
"status": "cancelled",
"frequency": "monthly",
"customer_id": 1,
"tea_ids": [
1,
2
]
}
},
{
"id": "2",
"type": "subscription",
"attributes": {
"id": 2,
"title": "Monthly Tea Subscription",
"price": "15.99",
"status": "cancelled",
"frequency": "monthly",
"customer_id": 1,
"tea_ids": [
1,
2
]
}
}, (etc.)
]
}