This is a sample app that will be used (for real) to track:
for a hobby job that my wife has.
$ cp config/database.yml.example config/database.yml
and adjust it to your local environmentFor a successful bundle install
, you'll need to sudo apt-get install libpq-dev
.
$ bundle install
# give a password to the main db user
$ sudo -u postgres psql postgres
postgres=# \password postgres
\q
# create a superadmin user for easier testing
$ sudo -u postgres createuser --superuser sale_trackr
$ sudo -u postgres psql
postgres=# \password sale_trackr
* uncomment `listen_addresses = 'localhost'` in `postgresql.conf`
$ rake db:setup
The application has an API to let you build your own client and use the application.
Just point all your requests to the /api
namespace and you'll be good to go.
Example: http://127.0.0.1/api/customers.json?token=y1ckhL3mB1GW985qaKRn
.
Note: The API requires a user token to validate requests. Examples using the authentication token.
http://127.0.0.1/api/customers.json?token=y1ckhL3mB1GW985qaKRn
$ curl http://127.0.0.1/api/customers.json?token=y1ckhL3mB1GW985qaKRn
$ curl --header "X-AUTH-TOKEN: y1ckhL3mB1GW985qaKRn" http://127.0.0.1/api/customers.json
Once a user exists, a unique authentication token is generated. All data requests to the API should use the token.
All data responses are scoped to the authentication token owner. That is, users don't have access to overall and other users data and related models.
The front-end code of the app, actually uses the API to retrieve all data presented to the user. This way we ensure that any data that can be displayed to the application user in a browser is also available to API clients.
Registration
/api/registration.json
curl -X POST --data "user[email]=johndoe@example.com&user[password]=password" \n
http://localhost:3000/api/registration.json
{
"id":1,
"email":"johndoe@example.com",
"authentication_token":"B43v36B7dQ1oaN6K9jRs",
"created_at":"2013-06-25T07:44:46Z",
"updated_at":"2013-06-25T07:44:46Z"
}
Customers are scoped to the user account making the request.
List all customers
/api/customers.json
http://127.0.0.1/api/customers.json?token=y1ckhL3mB1GW985qaKRn
.[
{
"id":8,
"name":"Dandre Satterfield",
"email":"cecile_dooley@gmail.com",
"phone":"1-801-142-8780 x5237",
"balance":9000.0,
"created_at":"2013-02-26T23:02:55Z",
"updated_at":"2013-02-27T02:20:17Z"
},
…
]
Show one customer
/api/customers/:id.json
http://127.0.0.1/api/customers/1.json?token=y1ckhL3mB1GW985qaKRn
{
"id":1,
"name":"Ms. Westley Shields",
"email":"gage.wuckert@hotmail.com",
"phone":"314-564-0035",
"balance":0.0,
"created_at":"2013-02-26T23:02:54Z",
"updated_at":"2013-02-27T02:20:17Z",
"transactions":[
{
"id":5,
"type":"Purchase",
"amount":12000.0,
"created_at":"2013-06-21T01:08:30Z",
"updated_at":"2013-06-21T01:09:13Z"
},
{
"id":4,
"type":"Payment",
"amount":4000.0,
"created_at":"2013-06-21T00:54:34Z",
"updated_at":"2013-06-21T00:54:34Z"
},
…
]
}
Create a customer
/api/customers.json
{customer: {name: cannot be blank}}
$ curl -X POST --data "token=9tbnwEBuV5jndAoNzXKq&customer[name]=James&customer[phone]=555-555-5555" \n
http://127.0.0.1/api/customers.json
{
"phone" : "555-555-5555",
"id" : 1,
"created_at" : "2013-06-25T08:08:51Z",
"email" : null,
"transactions" : [],
"updated_at" : "2013-06-25T08:08:51Z",
"name" : "James",
"balance" : 0
}
Update a customer
/api/customers/:id.json
{customer: {name: cannot be blank}}
$ curl -X POST --data "token=9tbnwEBuV5jndAoNzXKq&customer[name]=Xavier" \n
http://127.0.0.1/api/customers/1.json
Payments are scoped to the user account making the request.
List all paymentss
/api/payments.json
http://127.0.0.1/api/payments.json?token=y1ckhL3mB1GW985qaKRn
.[
{
"id":4,
"type":"Payment",
"amount":4000.0,
"created_at":"2013-06-21T00:54:34Z",
"updated_at":"2013-06-21T00:54:34Z",
"customer":{
"id":1,
"name":"Ms. Westley Shields",
"email":"gage.wuckert@hotmail.com",
"phone":"314-564-0035",
"balance":0.0,
"created_at":"2013-02-26T23:02:54Z",
"updated_at":"2013-02-27T02:20:17Z"
}
},
…
]
Show one payment
/api/payments/:id.json
http://127.0.0.1/api/payments/1.json?token=y1ckhL3mB1GW985qaKRn
{
"id":1,
"type":"Payment",
"amount":4000.0,
"created_at":"2013-06-21T00:54:34Z",
"updated_at":"2013-06-21T00:54:34Z",
"customer":{
"id":1,
"name":"Ms. Westley Shields",
"email":"gage.wuckert@hotmail.com",
"phone":"314-564-0035",
"balance":0.0,
"created_at":"2013-02-26T23:02:54Z",
"updated_at":"2013-02-27T02:20:17Z"
}
}
Create a payment
/api/payments.json
Update a payment
/api/payments/:id.json
Purchases are scoped to the user account making the request.
List all purchases
/api/purchases.json
http://127.0.0.1/api/purchases.json?token=y1ckhL3mB1GW985qaKRn
.[
{
"id":5,
"type":"Purchase",
"amount":12000.0,
"created_at":"2013-06-21T01:08:30Z",
"updated_at":"2013-06-21T01:09:13Z",
"customer":{
"id":1,
"name":"Ms. Westley Shields",
"email":"gage.wuckert@hotmail.com",
"phone":"314-564-0035",
"balance":0.0,
"created_at":"2013-02-26T23:02:54Z",
"updated_at":"2013-02-27T02:20:17Z"
},
"line_items":[
{
"id":335,
"name":"French Coat",
"color":"Gray",
"size":"38",
"cost":800.0,
"qty":1,
"price":1200.0,
"item_total":1200.0,
"created_at":"2013-06-21T01:40:44Z",
"updated_at":"2013-06-21T01:43:32Z"
},
...
]
},
...
]
Show one purchase
/api/purchases/:id.json
http://127.0.0.1/api/purchases/1.json?token=y1ckhL3mB1GW985qaKRn
{
"id":1,
"type":"Purchase",
"amount":12000.0,
"created_at":"2013-06-21T01:08:30Z",
"updated_at":"2013-06-21T01:09:13Z",
"customer":{
"id":1,
"name":"Ms. Westley Shields",
"email":"gage.wuckert@hotmail.com",
"phone":"314-564-0035",
"balance":0.0,
"created_at":"2013-02-26T23:02:54Z",
"updated_at":"2013-02-27T02:20:17Z"
},
"line_items":[
{
"id":335,
"name":"French Coat",
"color":"Gray",
"size":"38",
"cost":800.0,
"qty":1,
"price":1200.0,
"item_total":1200.0,
"created_at":"2013-06-21T01:40:44Z",
"updated_at":"2013-06-21T01:43:32Z"
},
...
]
}
Create a purchase
/api/purchases.json
Update a purchase
/api/purchases/:id.json