Contributors: Thomas Musselman | Riley McCullough | Sid Mann | A.J. Krumholz | Ken Lenhart
This is the back-end API for our Codename Demeter project. For for detailed information about the project please visit the front-end repository linked below.
This app includes a PostgreSQL database that stores garden, plot, and plant information for the app. Plant information is provided from CSV files of data scraped from the USDA's Plants Database. Plants were filtered so only plants with significant data are included.
The app also consumes two external APIs and consolidates the data to be consumed by our front end:
- Weather information for a user's garden is provided by consuming the OpenWeatherMap API
- USDA Plant Hardiness Zones are provided by https://phzmapi.org/ which is an API provided by Oregon State PRISM Climate Group
Application Deployed on Heroku
- Rails 5.2.6
- Ruby 2.7.4
- PostgreSQL Database
- CircleCI for CI/CD
- Heroku
- jsonapi-serializer for API response serialization.
git clone [email protected]:demeter-project/demeter-be.git
bundle install
rails db:{drop,create,migrate}
#load plant data from usda csv file:
rails csv_load:native_plants
#load test user garden/plots/plants (requires plant csv to be loaded):
rails db:seed
rails s
https://demeter-be.herokuapp.com/api/v1/
GET /plants/<plant_id>
Example Response:
{
"data": {
"id": "192",
"type": "plant",
"attributes": {
"common_name": "Heartleaf Arnica",
"usda_symbol": "ARCO9",
"scientific_name": "Arnica cordifolia",
"states": "AK, AZ, CA, CO, ID, MI, MT, ND, NM, NV, OR, SD, UT, WA, WY",
"duration": "Perennial",
**etc...**
}
}
}
GET /plants
Required Params:
- state_code: Two letter state code
- zip_code: 5-digit zip code for the planting location
Optional Params:
-
search_name: A string search query which returns only results with a similar or matching name. If no matching results, a null data value will be returned.
-
sort_by: Pass a plant attribute to sort the results based on that attribute. Available Options are any attribute listed in the plants table within the database schema above. Example Queries:
-
GET
https://demeter-be.herokuapp.com/api/v1/plants?state_code=CO&zip_code=80223
-
GET
https://demeter-be.herokuapp.com/api/v1/plants?state_code=CO&zip_code=80223&sort_by=ph_minimum
-
GET
https://demeter-be.herokuapp.com/api/v1/plants?state_code=CO&zip_code=80223&seach_name=columbine
Example Response:
{
"data": [
{
"id": "156",
"type": "plant",
"attributes": {
"common_name": "Heartleaf Arnica",
"usda_symbol": "ARCO9",
"scientific_name": "Arnica cordifolia",
"states": "AK, AZ, CA, CO, ID, MI, MT, ND, NM, NV, OR, SD, UT, WA, WY",
"duration": "Perennial",
"suitable_for_hz": true,
**etc....**
}
},
{
"id": "124",
"type": "plant",
"attributes": {
"common_name": "Heartleaf Arnica",
"usda_symbol": "ARCO9",
"scientific_name": "Arnica cordifolia",
"states": "AK, AZ, CA, CO, ID, MI, MT, ND, NM, NV, OR, SD, UT, WA, WY",
"duration": "Perennial",
"suitable_for_hz": false,
**etc....**
}
},
**etc...**
]
}
Notes
Plants returned in this query include an additional boolean attribute "suitable_for_hz" that specifies whether the plant is suitable in the provided zip_code.
See the database schema above for list of other attributes on a given plant.
- GET
/gardens
Required Params:
- user_id: The user's id.
Example Query:
- GET
https://demeter-be.herokuapp.com/api/v1/gardens?user_id=18
Example Response:
{
"data": [
{
"id": "1",
"type": "garden",
"attributes": {
"name": "My Garden",
"zip_code": 80023,
"state_code": "CO",
"user_id": "18"
}
},
{
"id": "2",
"type": "garden",
"attributes": {
"name": "My Second Garden",
"zip_code": 80023,
"state_code": "CO",
"user_id": "18"
}
}
]
}
GET /gardens/<garden_id>
Example Response:
{
"data": {
"id": "6",
"type": "garden",
"attributes": {
"name": "My Garden",
"zip_code": 80023,
"state_code": "CO",
"weather_forecast": [
{
"period": "2022-11-17T03:00:00.000Z",
"temp": 32.56,
"weather": "Few Clouds",
"icon_path": "http://openweathermap.org/img/wn/02n.png"
},
{
"period": "2022-11-17T09:00:00.000Z",
"temp": 30.7,
"weather": "Overcast Clouds",
"icon_path": "http://openweathermap.org/img/wn/04n.png"
},
**etc...(includes 10 weather periods in actual response)**
]
}
}
}
Notes:
When fetching a single garden, the seven day forecast for garden's location is included in the attributes of the garden.
GET /gardens/<garden_id>/plots
Example Response:
{
"data": [
{
"id": "1",
"type": "plot",
"attributes": {
"name": "Pink Flowers"
}
},
{
"id": "2",
"type": "plot",
"attributes": {
"name": "Ornamental Grasses"
}
},
**etc..**
]
}
GET /gardens/<garden_id>/plots/<plot_id>
Example Response
{
"data": {
"id": "15",
"type": "plot",
"attributes": {
"name": "Succulents",
"soil_ph_min": 5.7,
"soil_ph_max": 7,
"shade_tolerant?": true,
"contains_toxic?": true
}
}
}
Notes
soil_ph_min
, soil_ph_max
, and shade_tolerant
are calculated based on the plants within the plot. If there are currently no plants within the plot these values will be null.
GET /gardens/<garden_id>/plots/<plot_id>/plot_plants
Example Response
{
"data": [
{
"id": "3",
"type": "plot_plant",
"attributes": {
"plant_id": "15",
"plant_name": "Common Clover",
"quantity": 5,
"date_planted": "2022-05-18"
}
},
{
"id": "4",
"type": "plot_plant",
"attributes": {
"plant_id": "185",
"plant_name": "Columbine",
"quantity": null,
"date_planted": null
}
},
**etc...**
]
}
Notes:
If a plant has null values for quantity
and date_planted
then it has been added to a garden but not planted.
POST /gardens
Example Post Request JSON Body:
{
"name": "My Garden",
"zip_code": "80023",
"state_code": "CO",
"user_id": 15
}
Example Response
Response should match a GET gardens/<garden_id>
response for the newly created garden.
POST /gardens/<garden_id>/plots
Example Post Request JSON Body:
{
"name": "Colorado Wildflowers"
}
Example Response
Response should match a GET /gardens/<garden_id>/plots/<plot_id>
response for the newly created plot.
DELETE /gardens/<garden_id>
Notes:
Will return status 204 with no JSON response if the garden was successfully deleted.
DELETE /gardens/<garden_id>/plots/<plot_id>
Notes:
Will return status 204 with no JSON response if the plot was successfully deleted.
DELETE /gardens/<garden_id>/plots/<plot_id>/plot_plants/<plot_plant_id>
Notes:
Will return status 204 with no JSON response if the plot_plant was successfully deleted.
PATCH /gardens/<garden_id>/plots/<plot_id>
Example Patch Request JSON Body:
{
"plant_ids": [8, 148, 298, 1024, 9]
}
Example Response
The response should match a GET /gardens/<garden_id>/plots/<plot_id>
request response. The response will not include the added plants, however once the post request is made the plants can be retrieved with the GET /gardens/<garden_id>/plots/<plot_id>/plot_plants
endpoint.
Notes:
The intention of this endpoint is to add plants to a plot, but it could also be passed a "name" in the JSON body to update the name.
PATCH gardens/<garden_id>/plots/<plot_id>/plot_plants/<plot_plant_id>
Exampe Patch Request JSON Body:
{
"date_planted": 2022-5-13,
"quantity": 15
}
Example Response
{
"data": {
"id": "15",
"type": "plot_plant",
"attributes": {
"quantity": 15,
"date_planted": 2022-5-15,
"plant_id": 85,
"plant_name": "Wild Thornbush"
}
}
}
Notes:
This endpoint is intended to be used to record the planting of a plant in a garden after it has been added through the plant discover page.
Code Example Screenshots
Serializing plant information for the frontend
An example of one of our ActiveRecord models
The rake task used to populate our plants table, coming from USDA Plants database