api-based client/server applications with tdd and activeresource
DESCRIPTION
Wolf Arnold creates a demo application that uses ActiveResource. On github there is a repository that contains a client and a server app written in Rails to illustrate theActiveResource TDD approach presented on 7/20/2010 at the East Bay Ruby Meetup. http://github.com/wolframarnold/tdd_with_activeresourceTRANSCRIPT
API-based client/server API-based client/server applications with TDD and applications with TDD and
ActiveResource ActiveResource
Wolfram ArnoldWolfram Arnoldwww.rubyfocus.bizwww.rubyfocus.biz
In collaboration with:In collaboration with:Kurt SnyderKurt Snyder
papercheck.compapercheck.commarakana.commarakana.com
Database-backedDatabase-backed
DB
Application
ActiveRecord
SQL
API-backedAPI-backed
ClientApplication
ActiveResource
ServerApplication
API
JSON
DB
SQL
Tradeoffs?Tradeoffs?
DB-backed
Fast
ActiveRecord well developed
Complex relationships possible
Limited scalability—tight coupling
API-backed
Extra network & server latency
Complex relationships more difficult
Scales well to different front-ends—loose coupling
ClientApplication
(Flash or JS)
Frontend ScalabilityFrontend Scalability
ClientApplication
ActiveResource
ServerApplication
API
JSON
DB
SQL
ClientApplication
(Mobile)
Rails ActiveResourceRails ActiveResource
Model objects that behaves ActiveRecord objects
Maps CRUD operations to RESTful API
No Associations
No Validations (added in Rails 3)
Rougher around the edges than ActiveRecord
From CRUD to RESTFrom CRUD to REST
class Person < ActiveResource::Basesite “http://server.example.com/people”format :json
end
Person.create(:name => “Joe”)
→ POST /people, {'name':'Joe'}
Person.find(4)
→ GET /people/4
Resourceful RoutesResourceful Routes
map.resources :people (in config/routes.rb)
people_path, people_url “named route methods”
GET /people → “index” action
POST /people → “create” action
new_person_path, new_person_url
GET /people/new → “new” action
edit_person_path, edit_person_url
GET /people/:id/edit → “edit” action with ID
person_path, person_url
GET /people/:id → “show” action with ID
PUT /people/:id → “update” action with ID
DELETE /people/:id → “destroy” action with ID
Hyperactive ResourceHyperactive Resource
http://github.com/taryneast/hyperactiveresource
Adds Associations
Supports nested routes
/people/5/addresses/3
But: Cannot mix nested and non-nested routes for the same resource
Adds Validations
Let's do some codingLet's do some coding
Demo
RESTful Person Server API with JSON
HyperactiveResource-based client
TDD anyone?TDD anyone?
DB
Application
ActiveRecord
SQL
RSpec model testswith fixtures, factories
Test Databasewith transaction support
TDD ActiveRecord StyleTDD ActiveRecord Style
it “should create the object” dolambda { Person.create(:first_name => “Joe”)}.should change(Person, :count).by(1)
end
it “should destroy the object” dop = Factory.create(:person)lambda { p.destroy}.should change(Person, :count).by(-1)
end
API-backedAPI-backed
ClientApplication
ActiveResource
ServerApplication
API
JSON
DB
SQL
RSpec model test
Test DatabaseonTest Serverinstance!
Mocks anyone?Mocks anyone?
FakeWeb gem: http://github.com/chrisk/fakeweb
FakeWeb.register_uri(:get,"http://server.example.com/people",:body => "Hello World!")
Body is the mock object.
It should simulate the server response.
Great solution if it's a 3rd party server.
Problems with Mocks?Problems with Mocks?
If the server code is under our control...
What happens if the server API changes but the mock doesn't?
What process keeps the simulated server responses and the actual API in sync?
Better ideas?
Beyond MocksBeyond Mocks
Remote Specs
Rely on remote server running (in test environment)
Mechanism to set up data
Mechanism to inspect data
Mechanism to clean up data
Distributed Ruby “DRb”Distributed Ruby “DRb”
ClientApplication
DRb Client
ServerApplication
DRb Server
DRb
RemoteMethodInvocation
foo(args)
foo(args)
Demo DRb
Gotcha'sGotcha's
ActiveResource::Base.include_root_in_json
after_initialize hook for starting DRb server
:id problem for Objects, via DRb
Need to run server in test mode
Ideas/Questions:
Front Object in DRb?
rake task to start/stop server—reliably find process?
DRb port inflation—better way?
SummarySummary
Server application with REST controller
Client application with ActiveResource
Use DRb to:
test objects
inquire “actual” data
TDD with ActiveResource
BizConfBizConf
Aug 4-6, 2010
Amelia Island, FL
Discount code: WOLF
for 43% off
http://bizconf.org?coupon=WOLF
Rails & Web App Professionals, Entrepreneurs, Consultants
Small group
Network with Who's Who
Organized by Obie Fernandez of Hashrocket
Highlight: David Allen