An API to store data on where users need to crash for a night
Install with bundle install
.
- Fork and clone this repository.
- Install dependencies with
bundle install
. - Create a
.env
for sensitive settings (touch .env
). - Generate new
development
andtest
secrets (bundle exec rake secret
). - Store them in
.env
with keysSECRET_KEY_BASE_<DEVELOPMENT|TEST>
resepctively. - Run the API server with
bin/rails server
orbundle exec rake server
.
In order to make requests from your deployed client application, you will need
to set CLIENT_ORIGIN
in the environment (e.g. heroku config:set CLIENT_ORIGIN=https://<github-username>.github.io
).
Verb | URI Pattern | Controller#Action |
---|---|---|
POST | /sign-up |
users#signup |
POST | /sign-in |
users#signin |
PATCH | /change-password/:id |
users#changepw |
DELETE | /sign-out/:id |
users#signout |
GET | /profiles |
profiles#index |
GET | /profiles/:id |
profiles#show |
PATCH | /profiles/:id |
profiles#update |
POST | /couchposts |
couchposts#create |
GET | /couchposts |
couchposts#index |
GET | /couchposts/:id |
couchposts#show |
PATCH | /couchposts/:id |
couchposts#update |
DELETE | /couchposts/:id |
couchposts#destroy |
The create
action expects a POST of credentials
and profile
information identifying a new user and profile to create:
Request:
curl http://localhost:4741/sign-up \
--include \
--request POST \
--header "Content-Type: application/json" \
--data '{
"credentials": {
"email": "'"${EMAIL}"'",
"password": "'"${PASSWORD}"'",
"password_confirmation": "'"${PASSWORD}"'"
},
"profile": {
"given_name": "'"${GIVEN_NAME}"'",
"surname": "'"${SURNAME}"'",
"gender": "'"${GENDER}"'",
"dob": "'"${DOB}"'"
}
}'
EMAIL='[email protected]' PASSWORD='lauren' GIVEN_NAME='lauren' SURNAME='p' DOB='1993-01-16' sh scripts/sign-in.sh
Response:
HTTP/1.1 201 Created
Content-Type: application/json; charset=utf-8
{
"user": {
"id": 1,
"email": "[email protected]"
}
}
Request:
curl http://localhost:4741/sign-in \
--include \
--request POST \
--header "Content-Type: application/json" \
--data '{
"credentials": {
"email": "'"${EMAIL}"'",
"password": "'"${PASSWORD}"'"
}
}'
EMAIL='[email protected]' PASSWORD='lauren' sh scripts/sign-in.sh
Response:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
{
"user": {
"id": 1,
"email": "[email protected]",
"token": "BAhJIiVlZDIwZTMzMzQzODg5NTBmYjZlNjRlZDZlNzYxYzU2ZAY6BkVG--7e7f77f974edcf5e4887b56918f34cd9fe293b9f"
}
}
Request:
curl --include --request PATCH "http://localhost:4741/change-password/$ID" \
--header "Authorization: Token token=$TOKEN" \
--header "Content-Type: application/json" \
--data '{
"passwords": {
"old": "'"${OLDPW}"'",
"new": "'"${NEWPW}"'"
}
}'
ID=1 OLDPW='lauren' NEWPW='piss-ass' TOKEN='BAhJIiVlZDIwZTMzMzQzODg5NTBmYjZlNjRlZDZlNzYxYzU2ZAY6BkVG--7e7f77f974edcf5e4887b56918f34cd9fe293b9f' sh scripts/change-password.sh
Response:
HTTP/1.1 204 No Content
Request:
curl http://localhost:4741/sign-out/$ID \
--include \
--request DELETE \
--header "Authorization: Token token=$TOKEN"
ID=1 TOKEN='BAhJIiVlZDIwZTMzMzQzODg5NTBmYjZlNjRlZDZlNzYxYzU2ZAY6BkVG--7e7f77f974edcf5e4887b56918f34cd9fe293b9f' ID=1 sh scripts/sign-out.sh
Response:
HTTP/1.1 204 No Content
Verb | URI Pattern | Controller#Action |
---|---|---|
GET | /users |
users#index |
GET | /users/1 |
users#show |
Request:
curl http://localhost:4741/users \
--include \
--request GET \
--header "Authorization: Token token=$TOKEN"
TOKEN='BAhJIiVlZDIwZTMzMzQzODg5NTBmYjZlNjRlZDZlNzYxYzU2ZAY6BkVG--7e7f77f974edcf5e4887b56918f34cd9fe293b9f' sh scripts/users.sh
Response:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
{
"users": [
{
"id": 2,
"email": "[email protected]"
},
{
"id": 1,
"email": "[email protected]"
}
]
}
Request:
curl --include --request GET http://localhost:4741/users/$ID \
--header "Authorization: Token token=$TOKEN"
ID=2 TOKEN='BAhJIiVlZDIwZTMzMzQzODg5NTBmYjZlNjRlZDZlNzYxYzU2ZAY6BkVG--7e7f77f974edcf5e4887b56918f34cd9fe293b9f' ID=1 sh scripts/user.sh
Response:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
{
"user": {
"id": 1,
"email": "[email protected]"
}
}
All profile action requests must include a valid HTTP header Authorization: Token token=<token>
or they will be rejected with a status of 401 Unauthorized.
The index
action is a GET that retrieves all profiles.
Request:
curl http://localhost:4741/profiles \
--include \
--request GET \
--header "Authorization: Token token=$TOKEN"
TOKEN='BAhJIiVlZDIwZTMzMzQzODg5NTBmYjZlNjRlZDZlNzYxYzU2ZAY6BkVG--7e7f77f974edcf5e4887b56918f34cd9fe293b9f' sh scripts/profiles/index.sh
The response body will contain JSON containing an array of profiles, e.g.:
{
"profiles":[
{
"id":1,
"given_name":"Lauren",
"surname":"Kato",
"gender":"f",
"dob":"1993-01-16T00:00:00.000Z",
"editable":true
},
{
"id":2,
"given_name":"Emily",
"surname":"Kato",
"gender":"f",
"dob":"1993-01-16T00:00:00.000Z",
"editable":false
}
]
}
If a user
is logged in, then index
will return editable
as true for that user's profile.
The show
action is a GET that retrieves a given couchpost.
Request:
curl http://localhost:4741/profiles/$ID \
--include \
--request GET \
--header "Authorization: Token token=$TOKEN"
TOKEN='BAhJIiVlZDIwZTMzMzQzODg5NTBmYjZlNjRlZDZlNzYxYzU2ZAY6BkVG--7e7f77f974edcf5e4887b56918f34cd9fe293b9f' ID=5 sh scripts/couchposts/show.sh
The response body will contain a JSON object of that couchpost, e.g.:
{
"profile":{
"id":5,
"given_name":"Chrissy",
"surname":"Kato",
"gender":"f",
"dob":"1993-01-16T00:00:00.000Z",
"editable":false
}
}
Request:
curl http://localhost:4741/profiles \
--include \
--request PATCH \
--header "Content-Type: application/json" \
--header "Authorization: Token token=$TOKEN" \
--data '{
"profile": {
"given_name": "'"${GIVEN_NAME}"'",
"surname": "'"${SURNAME}"'",
"gender": "'"${GENDER}"'",
"dob": "'"${DOB}"'"
}
}'
TOKEN='BAhJIiVlZDIwZTMzMzQzODg5NTBmYjZlNjRlZDZlNzYxYzU2ZAY6BkVG--7e7f77f974edcf5e4887b56918f34cd9fe293b9f' ID=1 GIVEN_NAME='Lauren' SURNAME='McFace' GENDER='f' DOB='1993-01-01' sh scripts/profiles/update.sh
Response:
HTTP/1.1 204 No Content
The update
action is a PATCH that updates the profile who has authorization. It expects a PATCH of profile
specifying given_name
, surname
, gender
, and dob
.
If the request is successful, the response will have an HTTP status of 204 No Content.
If the request is unsuccessful, the response will have an HTTP status of 400 Bad Request.
All couchpost action requests must include a valid HTTP header Authorization: Token token=<token
or they will be rejected with a status of 401 Unauthorized.
The create
action is a POST that creates a new couchpost for the user signed in. It expects a POST of couchpost
specifying location
, date_needed
, and couch_found
. The user's id number automatically is assigned to profile_id
, as the two id numbers will be the same (see signup
).
Request:
curl http://localhost:4741/couchposts \
--include \
--request POST \
--header "Content-Type: application/json" \
--header "Authorization: Token token=$TOKEN" \
--data '{
"couchpost": {
"location": "'"${LOCATION}"'",
"date_needed": "'"${DATE_NEEDED}"'",
"couch_found": "'"${COUCH_FOUND}"'",
"profile_id": "'"${PROFILE_ID}"'"
}
}'
ID=1 TOKEN='BAhJIiVlZDIwZTMzMzQzODg5NTBmYjZlNjRlZDZlNzYxYzU2ZAY6BkVG--7e7f77f974edcf5e4887b56918f34cd9fe293b9f' LOCATION='Boston' DATE_NEEDED='2017-03-31' COUCH_FOUND='no' PROFILE_ID=1 sh scripts/profiles/update.sh
The response will have an HTTP status of 201 Created, and the body will contain JSON of the created couchpost:
{
"id":7,
"location":"Boston",
"date_needed":"2017-03-31",
"couch_found":"no",
"profile": 1,
"editable": true
}
The index
action is a GET that retrieves all couchposts.
Request:
curl http://localhost:4741/couchposts \
--include \
--request GET
sh scripts/couchposts/index.sh
The response body will contain JSON containing an array of couchposts, e.g.:
{
"couchposts":[
{
"id":8,
"location":"Back Bay",
"date_needed":"2017-03-31T00:00:00.000Z",
"couch_found":false,
"profile":1,
"editable":false
},
{
"id":7,
"location":"Somerville",
"date_needed":"2017-03-31T00:00:00.000Z",
"couch_found":true,
"profile":1,
"editable":false
}
]
}
If a user
is logged in, then index
will return editable
as true for that user's profile.
The show
action is a GET that retrieves a given couchpost.
Request:
curl http://localhost:4741/couchposts/$ID \
--include \
--request GET \
--header "Authorization: Token token=$TOKEN"
TOKEN='BAhJIiVlZDIwZTMzMzQzODg5NTBmYjZlNjRlZDZlNzYxYzU2ZAY6BkVG--7e7f77f974edcf5e4887b56918f34cd9fe293b9f' ID=5 sh scripts/couchposts/show.sh
The response body will contain a JSON object of that couchpost, e.g.:
{
"couchpost":{
"id":5,
"location":"GA",
"date_needed":"2017-03-31T00:00:00.000Z",
"couch_found":false,
"profile":1,
"editable":true
}
}
The update
action is a PATCH that updates a couchpost for a user who has authorization. It expects a PATCH of couchpost
specifying location
, date_needed
, and couch_found
. The user's id number automatically is assigned to profile_id
.
Request:
curl http://localhost:4741/couchposts/$ID \
--include \
--request PATCH \
--header "Content-Type: application/json" \
--header "Authorization: Token token=$TOKEN" \
--data '{
"couchpost": {
"location": "'"${LOCATION}"'",
"date_needed": "'"${DATE_NEEDED}"'",
"couch_found": "'"${COUCH_FOUND}"'"
}
}'
TOKEN='BAhJIiVlZDIwZTMzMzQzODg5NTBmYjZlNjRlZDZlNzYxYzU2ZAY6BkVG--7e7f77f974edcf5e4887b56918f34cd9fe293b9f' ID=1 LOCATION='Somerville' DATE_NEEDED='2017-02-22' COUCH_FOUND='yes' sh scripts/couchposts/show.sh
If the request is successful, the response will have an HTTP status of 204 No Content.
If the request is unsuccessful, the response will have an HTTP status of 400 Bad Request.
The destroy
action is a DELETE that deletes a couchpost for a user who has authorization.
Request:
curl http://localhost:4741/couchposts/$ID \
--include \
--request DELETE \
--header "Authorization: Token token=$TOKEN"
ID=1 TOKEN='BAhJIiVlZDIwZTMzMzQzODg5NTBmYjZlNjRlZDZlNzYxYzU2ZAY6BkVG--7e7f77f974edcf5e4887b56918f34cd9fe293b9f' ID=20 sh scripts/couchposts/destroy.sh
If the request is successful, the response will have an HTTP status of 204 No Content.
If the request is unsuccessful, the response will have an HTTP status of 400 Bad Request.
I learned a lot about serializers in this project. I had the most difficulty connecting the back-end to Ember, so that was the greatest challenge for me. I basically learned that the serializer is like the translator between the front-end and the back-end, but I have to point it in the right direction so the data flows the way I need it to.
I really want to implement friendships later down the line. I understand I'm going to want to use a recursive relationship for profiles, and I'm excited to move forward and learn more about implementing that kind of relationship.
- Ruby
- Ruby on Rails
- PostgreSQL