Table of Contents
This is the back-end of a hypothetical application to plan road trips. This app will allow users to see the current weather as well as the forecasted weather at the destination.
I used these user stories as a guide to how the front end will communicate with back-end through an API.
- Expose an API that aggregates data from multiple external APIs
- Expose an API that requires an authentication token
- Determine completion criteria based on the needs of other developers
- Research, select, and consume an API based on your needs as a developer
-
Ruby 2.7.2
-
Rails 5.2.6
Testing: rspec-rails, shoulda-matchers, simplecov, webmock, vcr
API: faraday, figaro, jsonapi-serializer
These instructions will give you a copy of the project up and running on your local machine for development and testing purposes.
- Fork and Clone the repo
- Install gem packages:
bundle install
- Setup the database:
rails db:create
- Run migrations:
rails db:migrate
- Create an account with Open Weather Map and request an API key
- Create an account with Geocode Address and request an API key
- Create an account with Unsplash and request an API key
- Install the Figaro gem:
bundle exec figaro install
- Add your API key to the
application.yml
created by Figaro:
MAPQUEST_KEY: your_api_key
OPENWEATHER_KEY: your_api_key
UNSPLASH_KEY: your_api_key
All endpoints can be viewed by running the rails server
command in your terminal. In your browswer, type in http://localhost:3000/{endpoint_get_request}
You can also view the response in Postman. Below are details about each endpoint and the type of response you can expect.
Request Type | URI |
---|---|
GET | /api/v1/forecast?location={location} |
GET | /api/v1/backgrounds?location={location} |
GET | /api/v1/breweries?location={location}&quantity={quantity} |
POST | /api/v1/users |
POST | /api/v1/sessions |
POST | /api/v1/road_trip |
Below are details on how to use each endpoint and the relevant Front End wireframes.
Request Type | URI | Description |
---|---|---|
GET | /api/v1/forecast?location={location} | Returns current forecast for given location. Location must be sent as 'city, state abbreviation' like 'Boston, MA' or 'New York, NY' |
GET | /api/v1/backgrounds?location={location} | Returns url and details of a background image to display for given location. Location must be sent as 'city, state abbreviation' like 'Boston, MA' or 'New York, NY' |
Request:
GET /api/v1/forecast?location=denver,co
Content-Type: application/json
Accept: application/json
Response:
{
"data": {
"id": null,
"type": "forecast",
"attributes": {
"current_weather": {
"datetime": "2020-09-30 13:27:03 -0600",
"temperature": 79.4,
etc
},
"daily_weather": [
{
"date": "2020-10-01",
"sunrise": "2020-10-01 06:10:43 -0600",
etc
},
{...} etc
],
"hourly_weather": [
{
"time": "14:00:00",
"conditions": "cloudy with a chance of meatballs",
etc
},
{...} etc
]
}
}
}
Request:
GET /api/v1/backgrounds?location=boston,ma
Content-Type: application/json
Accept: application/json
Response:
{
"data": {
"id": null,
"type": "image",
"attributes": {
"info": {
"location": "boston,ma",
"image_url": "https://images.unsplash.com/photo-1569259907653-1bf37acbcac9?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=MnwyNTEwMzZ8MHwxfHNlYXJjaHwxfHxib3N0b24lMkNtYXxlbnwwfHx8fDE2MzMzNzIwNzQ&ixlib=rb-1.2.1&q=80&w=1080",
"credit": {
"source": "unsplash.com",
"author": "redaska",
"logo": "https://images.unsplash.com/profile-1570635599993-4aeaa2f37308image?ixlib=rb-1.2.1&q=80&fm=jpg&crop=faces&cs=tinysrgb&fit=crop&h=64&w=64"
}
}
}
}
}
Request | URI | Description |
---|---|---|
POST | /api/v1/users | A post request can be sent to the above uri, sending over the email, password, and password confirmation in the body of the request as JSON. If successful, create a user in your database, and generate a unique api key associated with that user, with a 201 status code. The response should NOT include the password in any form. Must include email, password and password confirmation. |
Request:
POST /api/v1/users
Content-Type: application/json
Accept: application/json
{
"email": "whatever@example.com",
"password": "password",
"password_confirmation": "password"
}
Response:
{
"data": {
"type": "users",
"id": "1",
"attributes": {
"email": "whatever@example.com",
"api_key": "jgn983hy48thw9begh98h4539h4"
}
}
}
Request | URI | Description |
---|---|---|
POST | /api/v1/sessions | A post request can be sent to the above uri, sending over email and password in the body of the request as JSON. If successful, it will return the given user's email and api_key. Must include email and password. |
Request:
POST /api/v1/sessions
Content-Type: application/json
Accept: application/json
{
"email": "whatever@example.com",
"password": "password"
}
Response:
{
"data": {
"type": "users",
"id": "1",
"attributes": {
"email": "whatever@example.com",
"api_key": "jgn983hy48thw9begh98h4539h4"
}
}
}
Request | URI | Description |
---|---|---|
POST | /api/v1/road_trip | A post request can be sent to the above uri, sending over an origin (ex. 'Boston, MA'), a destination (ex. 'Denver, CO'), and a valid api key in the body of the request. If the locations are able to be traversed via car, and the api key is valid, the response will send the destination and origin city, total travel time, and estimated weather upon arrival at destination city. Must include both origin and destination city and valid api key |
Request:
POST /api/v1/road_trip
Content-Type: application/json
Accept: application/json
body:
{
"origin": "Denver,CO",
"destination": "Estes Park, CO",
"api_key": "jgn983hy48thw9begh98h4539h4"
}
Response:
{
"data": {
"id": null,
"type": "roadtrip",
"attributes": {
"start_city": "Denver, CO",
"end_city": "Estes Park, CO",
"travel_time": "2 hours, 13 minutes"
"weather_at_eta": {
"temperature": 59.4,
"conditions": "partly cloudy with a chance of meatballs"
}
}
}
}
Request | URI | Description |
---|---|---|
GET | /api/v1/breweries?location={location}&quantity={quantity} | Returns list of open breweries in given location and the current weather forecast in that city. Location must be sent as 'city, state abbreviation' like 'Boston, MA' or 'New York, NY'. Quantity must be a positive number. |
Request:
GET /api/v1/breweries?location=boston,ma&quantity=10
Content-Type: application/json
Accept: application/json
Response:
{
"data": {
"id": "null",
"type": "breweries",
"attributes": {
"destination": "boston, ma",
"forecast": {
"summary": "overcast clouds",
"temperature": "-355 F"
},
"breweries": [
{
"id": 10118,
"name": "Democracy Brewing",
"brewery_type": "brewpub"
},
{
"id": 14371,
"name": "Slesar Bros Brewing Co - Boston Beer Works",
"brewery_type": "brewpub"
},
{
"id": 12636,
"name": "Mighty Squirrel",
"brewery_type": "contract"
},
{
"id": 11341,
"name": "Harpoon Brewery",
"brewery_type": "regional"
},
{
"id": 14447,
"name": "Somerville Brewing Company",
"brewery_type": "micro"
},
{
"id": 9686,
"name": "Cheeky Monkey Brewing Co / Lucky Strike Jillians",
"brewery_type": "brewpub"
},
{
"id": 12835,
"name": "Mystic Brewery",
"brewery_type": "micro"
},
{
"id": 10246,
"name": "Dorchester Brewing Company",
"brewery_type": "micro"
},
{
"id": 10261,
"name": "Down the Road Brewery",
"brewery_type": "micro"
},
{
"id": 14372,
"name": "Slesar Bros Brewing Co - Boston Beer Works",
"brewery_type": "brewpub"
}
]
}
}
}
Run bundle exec rspec
to run the test suite