Sunday, March 16, 2014

A Process for Creating a Ruby On Rails API ~ by Michael Droz

Sprint 1: Begins February 7th, Ends March 1st

Sprint Goal: 
To develop a thin slice through the entire API including an initial production deployment. 
    Stories included:

  •     Setup development environment with Rails 4.0+ and Git
  •     Integrate local Git with GitHub and Heroku Production environment
  •     Create initial API using Rails-API gem (stripped down rails)
  •     Create initial conceptual database design 
  •     Create initial models for two *guaranteed resources
    • /people
    • /deeds
  •      Create APIgee account + spike on how to create and manage APIs
  •      Create initial API proxy with one *guaranteed policy
    • Require API::Key
  •      Validate thin slice with the following test cases
    • Can push local code to GitHub
    • Can push GitHub repository to Heroku
    • Can't access API without API Key
    • With API Key can GET people and deed resources via CURL or other web based REST Client. 
    • With API Key can Create people resource via CURL or other web based REST Client. 

Step 1: Resource Design 
In a Google spreadsheet document the following: 
1. Resources (objects)
2. URLs and HTTP methods
Application Data ModelResource ModelStandard MethodsResource Desc
API ENTRY POINThttp://helpiado-test.apigee.net/v1/helpad-production/
People/entrypoint/peopleGETReturns 20 most recent
/entrypoint/people/newPOSTCreates new user
/entrypoint/people/updatePOST
/entrypoint/people/destroyPOSTDestroys the person specified
Deeds/entrypoint/deedsGETReturns 20 most recent
People/entrypoint/deedsPOSTCreates a new deed
People/entrypoint/deedsPOST
People/entrypoint/deedsPOSTDestroys the deed specified

Step 2: Create new project and models for resources
rails-api new <project_name>
rails g scaffold <model> name
rake db migrate

Step 3: Initiate Git w/GitHub & Heroku
Create GitHub repository at www.github.com
Now initiate git locally 
git init
git commit 
git remote add origin https://gihub.com/<username>/<repositoryname.git>
heroku create
git push heroku master

Step 4: Create APIgee proxy and first policy
Create API account
Create new API Proxy
Add resources to API Proxy
Add policy: Require API::Key

Step 5: Test API using RESTful Client

Step 6: Create diagram that represents your "thin slice" topology 
Step 7: Document Sprint Results

  • Completed Stories
    • All
  • Unexpected Issues
    • Required to upgrade database from SQLite3 to PostgreSQL :: Heroku no longer supports SQLite3 in production. [impact: 6 hours]
    • Issues updating resource parameters because Rails 4 now requires you to explicitly tell it which attributes to permit and require. [impact: 16 hours]

Sprint 2: Begins March 3rd, Ends March 14

Sprint Goal: 
To develop a second thin slice through the entire API and production topology.  
    Stories included:

  • Create relationship between people/deed entities (people have many deeds) (DONE)
    • People Model: Added has_many :deedsdependent:destroy
    • Deed Model: Added belongs_to :person
    • Enforce person_id foreign key integrity (person_id being added to deed column valid)
      • Deed Model: Added validates :person:presence =>true
  • Iterate on people/deed entities (focus on attributes) (DONE)
    • Three migrations
      • AddPersonIdToDeeds
        • add_column ...
        • add_index ...
      • FixDescriptionColumn
        • rename_column ...
      • AddConstraintToDeedsPersonIdColumn
        • change_column ... :null =>false
  • Fix insecure database.yml configuration (DONE)
    • vim database.yml
    • username: ENV["PSQL_USERNAME"]
    • password: ENV["PSQL_PASSWORD"]
    • Add Unix Environment Variables via Heroku CLI (Command line interface)
      • heroku config:add PSQL_USERNAME=username_from_Heroku --app <yourapp>
      • heroku config:add PSQL_PASSWORD=password_from_Heroku --app<yourapp>
  • Iterate on resources
    • people/
      • update
      • destroy
    • deeds/
      • create
      • get
      • update
      • destroy 
  • Lock-down direct access to API and require APIgee API key for all clients. Basically force API access through API Proxy. (DONE)
    • Added Ruby's http_basic_authenticate_with method to Application Controller 
      • Had to add this module since the Rails-API framework ships without it
        • class ApplicationController < ActionController::API                                                                                                                                                                                                        
            include ActionController::HttpAuthentication::Basic::ControllerMethods
    • Added Unix environment variable for API Proxy credentials
      • http_basic_authenticate_with nameENV["BASE_AUTH_NAME"], passwordENV["BASE_AUTH_PASS"
    • Added API Proxy credentials via apigee's "assign message" policy
      • name="Authentication"
      • Basic <base64 encoded username:password>
  • Validate second thin slice through following test cases:
    • TBD
Document Sprint Results
  • Unexpected Issues
    • Unplanned vacation [impact: 24 hours]
    • Migration to Chromebox for primary development [impact: 16 hours]
    • Unable to deploy to Heroku from Nitrous.io. Had to recreate Heroku environment [impact: 2 hours] - need to track to make sure this isn't a recurring problem on Nitrous.io. 
Michael Droz Current Development Stack: End of Sprint 2

  • Dev Box: Toshiba CB35 Chromebook
  • IDE & Unix Development Environment: Nitrous.IO
  • Production Environment: Heroku w/PostgreSQL
  • API Proxy: Apigee.com 

Sprint 3: =begin March 17th, =end March 28th

Sprint Goal: 
To integrate Helpiado API with Twitter API, enable registration and login via Twitter OAUTH and develop first client using Node.js that can display the deed feed and allow a user to vote up deeds.

    Stories included: TBD 

  • Spike on Twitter API
    • Create account
    • Ruby wrappers
    • Twitter OAUTH
    • Consuming resources 
  • Enable registration and login via Helpiado API 
    • Internal API clients (website, android, iOS apps)
    • 3rd party clients via developer community
  • Spike on Node.js via Nitrous.IO
    • Get backup to speed on how to wrangle Node.js into submission
  • Implement Voting Subsystem (IN PROGRESS)
    • Create Design Proposal (DONE - 3/20)
    • Create scaffold :: rails generate scaffold Vote (DONE - 3/15)
    • Create/Update supporting entities 
      • Added accumulative_score to Deeds
      • Added vote_balance to People
      • Need to create entity to hold logs of each vote cast and each vote granted
    • Create supporting models
    • Create/Update supporting controllers
      • Added vote_balance = 50 to user.create in People Controller to grant each user 50 votes upon initial registration. 
  • Create first API client using Node.js (for internal website)
    • Internal client to use API Proxy just as any other 3rd party client 
    • Allow developer to request and receive apikey via agigee developer portal
  • Complete agigee api training 

-----------------------------------------------------------------------------------
Here's a photos of me after my father, Michael Droz Sr, first explained to me how cool APIs were going to be. I am sure I was contemplating how long it would be before we would build our first Ruby on Rails API together. At this time we weren't living in San Francisco, San Carlos nor St. Joseph, we were living in the technology hub known as Seattle. 
Michael Droz at the Seattle Center.