Create a RESTful api that helps to manage a list of art information. Include scripts to load all your data. Provide developer documentation to minimize on-boarding friction. This is an "open book" test. Use all your resouces including previous repos, videos, online guides, etc. for assistance. However, communication with other students verbally or electronically is not permitted.
READ THESE INSTRUCTIONS TWICE. READ THESE INSTRUCTIONS CAREFULLY.
- Fork the repo
Sign in to your GitHub account and fork the following repo to your account:
https://github.com/jrs-innovation-center/art-api-exam-nolist
- Clone your fork
Clone your fork to your local machine and install the project's dependencies.
$ git clone <url>
$ cd art-api-exam-nolist
$ npm install
Your test will be graded using the following grading scale:
- Successfully complete the first 5 steps to receive a grade of 'Meets Expectations'.
- Complete the first 6 steps to receive a grade of 'Exceeds Expectations'.
- Complete all the steps to receive a grade of 'Outstanding'.
- You have until Monday at 12 p.m. to complete the test.
- Send your instructor a direct message containing your repo url before the exam deadline.
-
Using the existing file named load-data.js, create a program that adds the following paintings into a CouchDB database named
<your first name>Art
. Ex:TripArt
: -
Create an npm script named
load
that runs your load-data.js program. -
Test this program by running
npm run load
from your terminal.If you're interacting with CouchDB within IBM Bluemix/Cloudant or Roo, remember to keep your API key and password (secret) safe. Do not share on GitHub.
[ { "_id": "painting_starry-night", "name": "The Starry Night", "type": "painting", "movement": "post-impressionism", "artist": "Vincent van Gogh", "yearCreated": 1889, "museum": {name: "Museum of Modern Art", location: "New York"} }, { "_id": "painting_water-lilies-nympheas", "name": "Water Lilies Nympheas", "type": "painting", "movement": "impressionism", "artist": "Claude Monet", "yearCreated": 1907, "museum": {name: "Art Gallery of Ontario", location: "Toronto"} }, { "_id": "painting_last-supper", "name": "The Last Supper", "type": "painting", "movement": "Renaissance", "artist": "Leonardo da Vinci", "yearCreated": 1495, "museum": {name: "Santa Maria delle Grazie", location: "Milan"} }, { "_id": "painting_sunday-afternoon-on-the_island-of-la-grande-jatte", "name": "A Sunday Afternoon on the Island of La Grande Jatte", "type": "painting", "movement": "impressionism", "artist": "Georges Seurat", "yearCreated": 1884, "museum": {name: "Art Institute of Chicago", location: "Chicago"} }, { "_id": "painting_guernica", "name": "Guernica", "type": "painting", "movement": "surrealism", "artist": "Pablo Picasso", "yearCreated": 1937, "museum": {name: "Museo Nacional Centro de Arte Reina Sofía", location: "Madrid"} }, { "_id": "painting_bal-du-moulin-de-la-galette", "name": "Bal du moulin de la Galette", "type": "painting", "movement": "impressionism", "artist": "Pierre-Auguste Renoires", "yearCreated": 1876, "museum": {name: "Musée d’Orsay", location: "Paris"} } ]
Review the information below and create the described functionality.
Your api should run on port 4000.
POST /paintings
Creates a painting. The request body must contain a JSON object that represents the painting being created. The request body must include the name
, movement
, artist
, yearCreated
, and museum
fields.
- Use the
type
andname
fields in the creation of the_id
value. - DO NOT ALLOW the articles "a" or "the" in the beginning of the name for the primary key value.
- Slugify the
name
field.
In the example below the name of the painting to create is "The Persistence of Memory". When created the painting should have a primary key value of
_id: "painting_persistence-of-memory"
Sample Request
POST /paintings
Sample Request Body JSON Data
{
"name": "The Persistence of Memory",
"movement": "surrealism",
"artist": "Salvador Dali",
"yearCreated": 1931,
"museum": {name: "Musuem of Modern Art", location: "New York"}
}
Sample Response (your rev
values will vary)
{
"ok": true,
"id": "painting_persistence-of-memory",
"rev": "1-c617189487fbe325d01cb7fc74acf45b"
}
GET /paintings/{id}
Retrieves a specific painting as identified by the {id}
route parameter.
Sample Request
GET /paintings/painting_bal-du-moulin-de-la-galette
Sample Response
{
"_id": "painting_bal-du-moulin-de-la-galette",
"_rev": "1-c617189487fbe325d01cb7fc74acf45b",
"name": "Bal du moulin de la Galette",
"type": "painting",
"movement": "impressionism",
"artist": "Pierre-Auguste Renoires",
"yearCreated": 1876,
"museum": {name: "Musée d’Orsay", location: "Paris"}
}
PUT /paintings/{id}
Updates a specific painting as identified by the {id}
route parameter. The request body must contain a JSON object that represents the painting being updated. The request body must include the _id
, _rev
, name
, movement
, artist
, yearCreated
, museum
, and type
fields. Not providing the most recent _rev
value will cause an 409 - conflict
error to occur.
Sample Request
PUT /paintings/painting_bal-du-moulin-de-la-galette
Sample Request Body JSON Data
{
"_id": "painting_bal-du-moulin-de-la-galette",
"_rev": "1-c617189487fbe325d01cb7fc74acf45b",
"name": "Bal du moulin de la Galette",
"type": "painting",
"movement": "impressionism",
"artist": "Pierre-Auguste Renoires",
"yearCreated": 1877,
"museum": {name: "Musée d’Orsay", location: "Paris"}
}
200 Sample Response
{
"ok": true,
"id": "painting_bal-du-moulin-de-la-galette",
"rev": "2-7e9b8cac710e70bfe0bef2de7bb3cfdb"
}
DELETE /paintings/{id}
Deletes a specific painting as identified by the {id}
route parameter.
200 Sample Request
DELETE /paintings/painting_bal-du-moulin-de-la-galette
Sample Response
{
"ok": true,
"id": "painting_bal-du-moulin-de-la-galette",
"rev": "3-fdd7fcbc62477372240862772d91c88f"
}
Create developer on-boarding instructions by creating a README.md file. Include the following sections.
Within the Getting Started section of the readme provide guidance on how to:
- Create a database
- Clone your repo
- Install dependencies
- Establish environment variables such as key and secrets to create a database url
- Load your data.
- Start the API
- Make your first
GET
call within the browser.
Within your readme, include a Basics section containing the following sections:
-
Base URL - All endpoints within the paintings are located at the following base URL
-
Scheme - what scheme does your api support?
-
HTTP Verbs - what verbs does your api support? How does each verb relate to each of the routes for your entities, such as paintings?
-
Content Types
-
Response Status Codes - Include a listing of common successful and error status codes that a developer could encounter with your API. For example, what causes a painting not to be found? What causes a resource conflict when updating or adding a painting? What causes a bad request? See the section titled Response status codes in SKY API Docs Basics
For each status code include:
-
the status code
-
a description of the status code
Enhance the api by supporting the ability to create, read, update, and delete artists.
POST /artists
GET /artists/{id}
PUT /artists/{id}
DELETE /artists/{id}
Don't forget to modify your load data script to load in the artist data, too.
Tip: You may want to consider creating a new "feature" branch to help manage the changes to your code. When the code within the branch is stable, you can merge the branch into the master branch. After merging, delete the "feature" branch.
Within the lib folder, refactor the following functionality into library files.
-
\lib\pk-generator.js - Create a common primary key generator function. Export the function from the NodeJS module. Refactor your code to utilize the function.
-
\lib\check-required-fields.js - Create a function that checks the data within the incoming request body for both POSTs and PUTs. The function should accepts 3 parameters/arguments:
- HTTP Verb
- An array of required fields/keys
- An object containing request body
The function should return an empty array if all required fields are present within the request body. Otherwise, return an array of missing fields. Export the function from the NodeJS module. Refactor your code to utilize the function.
Tip: You may want to consider creating a new "feature" branch to help manage the changes to your code. When the code within the branch is stable, you can merge the branch into the master branch. After merging, delete the "feature" branch.
GET /paintings
Returns a collection of paintings sorted by painting name. An optional limit
query parameter provides a limit on the number of objects returned. Default limit
value is 5.
Hint: Consider using either
options
within allDocs() or Ramda to provide the limit functionality.
Examples
-
GET /paintings?limit=2
returns an JSON array of 2 paintings.Sample Response
[ { "_id": "painting_bal-du-moulin-de-la-galette", "_rev": "5-2bac91fbd33b6612e4ea7da0552c91ca", "name": "Bal du moulin de la Galette", "type": "painting", "movement": "impressionism", "artist": "Pierre-Auguste Renoires", "yearCreated": 1876, "museum": { "name": "Musée d’Orsay", "location": "Paris" } }, { "_id": "painting_guernica", "_rev": "5-a8b803395d7cb6154f63c627571a5575", "name": "Guernica", "type": "painting", "movement": "surrealism", "artist": "Pablo Picasso", "yearCreated": 1937, "museum": { "name": "Museo Nacional Centro de Arte Reina Sofía", "location": "Madrid" } } ]
- Create a
filter
query parameter on theGET /paintings
endpoint to provide flexible search capability. - Provide the ability to filter paintings by name, movement, artist and year created.
- In your api url's query string, the
filter
query parameter may be used in conjunction with thelimit
query parameter.
Hint: Consider using Mango Queries or Ramda to provide the filter.
Example
-
Filter by movement and limit to five paintings
GET /art/paintings?filter=movement:surrealism&limit=5
Sample Results
[ { "_id": "painting_guernica", "_rev": "1-ccd60fb0ca42d879d048f083b95cfdcb", "name": "Guernica", "type": "painting", "movement": "surrealism", "artist": "Pablo Picasso", "yearCreated": 1937, "museum": { "name": "Museo Nacional Centro de Arte Reina Sofía", "location": "Madrid" } } ]