Presented at Confoo (Montreal, Canada) on 3/1/2013
In this talk I’ll show you how to build your application and get a working, well tested, and useable API in the process, with almost no extra overhead. I’ll also show you how to do it without making your controllers a mess of respond_to blocks. If anything, you’re controllers will become cleaner and leaner.
21. SOA Pros
• Scales Easily
Monday, February 25, 13
22. SOA Pros
• Scales Easily
• Separate Concerns/Very Clean
Monday, February 25, 13
23. SOA Pros
• Scales Easily
• Separate Concerns/Very Clean
• Can be easier to maintain
Monday, February 25, 13
24. SOA Pros
• Scales Easily
• Separate Concerns/Very Clean
• Can be easier to maintain
• Solid Architecture
Monday, February 25, 13
25. SOA Pros
• Scales Easily
• Separate Concerns/Very Clean
• Can be easier to maintain
• Solid Architecture
• Easier to refactor/rebuild
Monday, February 25, 13
27. SOA Cons
• Can be more difficult to maintain
Monday, February 25, 13
28. SOA Cons
• Can be more difficult to maintain
• More complex deploys
Monday, February 25, 13
29. SOA Cons
• Can be more difficult to maintain
• More complex deploys
• Managing several applications
Monday, February 25, 13
30. SOA Cons
• Can be more difficult to maintain
• More complex deploys
• Managing several applications
• Potential for ‘out-of-sync’ apps
Monday, February 25, 13
31. SOA Cons
• Can be more difficult to maintain
• More complex deploys
• Managing several applications
• Potential for ‘out-of-sync’ apps
• More difficult to test integration
Monday, February 25, 13
42. class
TodosController
<
ApplicationController
def
index
@todos
=
Todo.all
end
def
show
@todo
=
Todo.find(params[:id])
end
def
new
@todo
=
Todo.new
end
def
edit
@todo
=
Todo.find(params[:id])
end
def
create
@todo
=
Todo.new(params[:todo])
if
@todo.save
redirect_to
@todo,
notice:
'Todo
was
successfully
created.'
else
render
action:
"new"
end
end
def
update
@todo
=
Todo.find(params[:id])
if
@todo.update_attributes(params[:todo])
redirect_to
@todo,
notice:
'Todo
was
successfully
updated.'
else
render
action:
"edit"
end
end
def
destroy
@todo
=
Todo.find(params[:id])
@todo.destroy
redirect_to
todos_path,
notice:
'Todo
was
successfully
destroyed.'
end
end
Monday, February 25, 13
46. class
Api::V1::TodosController
<
ApplicationController
respond_to
:json
before_filter
do
request.format
=
:json
end
def
index
@todos
=
Todo.all
respond_with
@todos
end
def
show
@todo
=
Todo.find(params[:id])
respond_with
@todo
end
def
create
@todo
=
Todo.new(params[:todo])
if
@todo.save
respond_with
@todo
else
render
json:
@todo.errors,
status:
:unprocessable_entity
end
end
def
update
@todo
=
Todo.find(params[:id])
if
@todo.update_attributes(params[:todo])
respond_with
@todo
else
render
json:
@todo.errors,
status:
:unprocessable_entity
end
end
def
destroy
@todo
=
Todo.find(params[:id])
@todo.destroy
head
:no_content
end
end
Monday, February 25, 13
47. version your API!
Api::V1::TodosController
/api/v1/todos
Monday, February 25, 13
59. Cross-origin
Resource Sharing
Monday, February 25, 13
60. rack-cors
https://github.com/cyu/rack-cors
Monday, February 25, 13
61. module
YourApp
class
Application
<
Rails::Application
#
...
config.middleware.use
Rack::Cors
do
allow
do
origins
'*'
resource
'*',
headers:
:any,
methods:
[:get,
:post,
:put,
:delete,
:options]
end
end
end
Monday, February 25, 13
63. JavaScript Pros
• Scales Easily/Pushes processing to client side
Monday, February 25, 13
64. JavaScript Pros
• Scales Easily/Pushes processing to client side
• Separate Concerns/Very Clean
Monday, February 25, 13
65. JavaScript Pros
• Scales Easily/Pushes processing to client side
• Separate Concerns/Very Clean
• Can be easier to maintain
Monday, February 25, 13
66. JavaScript Pros
• Scales Easily/Pushes processing to client side
• Separate Concerns/Very Clean
• Can be easier to maintain
• “Responsive/Native” feel for clients
Monday, February 25, 13
67. JavaScript Pros
• Scales Easily/Pushes processing to client side
• Separate Concerns/Very Clean
• Can be easier to maintain
• “Responsive/Native” feel for clients
• Easily consumes your API
Monday, February 25, 13
69. JavaScript Cons
• Can be more difficult to maintain
Monday, February 25, 13
70. JavaScript Cons
• Can be more difficult to maintain
• Multiple languages (backend/front-end)
Monday, February 25, 13
71. JavaScript Cons
• Can be more difficult to maintain
• Multiple languages (backend/front-end)
• Difficult to test integration
Monday, February 25, 13
72. JavaScript Cons
• Can be more difficult to maintain
• Multiple languages (backend/front-end)
• Difficult to test integration
• JavaScript
Monday, February 25, 13
73. JavaScript Cons
• Can be more difficult to maintain
• Multiple languages (backend/front-end)
• Difficult to test integration
• JavaScript
• Paradigm shift in architecture
Monday, February 25, 13
74. JavaScript Cons
• Can be more difficult to maintain • Accessibility issues
• Multiple languages (backend/front-end)
• Difficult to test integration
• JavaScript
• Paradigm shift in architecture
Monday, February 25, 13
75. JavaScript Cons
• Can be more difficult to maintain • Accessibility issues
• Multiple languages (backend/front-end) • SEO concerns
• Difficult to test integration
• JavaScript
• Paradigm shift in architecture
Monday, February 25, 13
76. JavaScript Cons
• Can be more difficult to maintain • Accessibility issues
• Multiple languages (backend/front-end) • SEO concerns
• Difficult to test integration • !!Internet Explorer!!
• JavaScript
• Paradigm shift in architecture
Monday, February 25, 13
88. class
TodosController
<
ApplicationController
def
index
@todos
=
ApiLib::Todo.all
end
def
show
@todo
=
ApiLib::Todo.find(params[:id])
end
def
new
@todo
=
ApiLib::Todo.new
end
def
edit
@todo
=
ApiLib::Todo.find(params[:id])
end
def
create
@todo
=
ApiLib::Todo.new(params[:todo])
if
@todo.save
redirect_to
@todo,
notice:
'Todo
was
successfully
created.'
else
render
action:
"new"
end
end
def
update
@todo
=
ApiLib::Todo.find(params[:id])
if
@todo.update_attributes(params[:todo])
redirect_to
@todo,
notice:
'Todo
was
successfully
updated.'
else
render
action:
"edit"
end
end
def
destroy
@todo
=
ApiLib::Todo.find(params[:id])
@todo.destroy
redirect_to
todos_path,
notice:
'Todo
was
successfully
destroyed.'
end
end
Monday, February 25, 13
89. hey! there is
duplicate* code
now
Monday, February 25, 13
90. is there? or did we
just move it
around?
Monday, February 25, 13
101. class
TodosController
<
ApplicationController
def
index
res
=
Api::V1::TodosController.action(:index).call(env)
@todos
=
JSON.parse(res[2].body).map
do
|data|
OpenStruct.new(data)
end
end
end
Monday, February 25, 13
102. projects
worth noting
Monday, February 25, 13