'activate' post 'suspend' ! ! resources :projects end end end do member do post 'archive' collection do get 'archived', to: 'archived_projects#index' , to: 'active_projects#index' , to: 'suspended_projects#index' , to: 'archived_projects#create' , to: 'active_projects#create' , to: 'suspended_projects#create' post 'create_review'
'activate' post 'suspend' ! ! resources :projects end end end do member do post 'archive' collection do get 'archived' resources :reviews, only: :create , to: 'archived_projects#index' , to: 'active_projects#index' , to: 'suspended_projects#index' , to: 'archived_projects#create' , to: 'active_projects#create' , to: 'suspended_projects#create'
I want JSON! Hey, I’m an Enterprise Java Application and I want XML! (Ha Ha, Business!) ¯\_(ツ)_/¯ Oi, soy un browser e quiero HTML! response in JSON respuesta en HTML response in XML Client B Client C content negotiation The process in which client and server determine the best representation for a response when many are available.
module API class ProjectsController < ApplicationController respond_to :json, :xml ! def index @projects = Project.all ! respond_with(@projects) end end end
ApplicationController def index @projects = Project.recent ! respond_to do |format| format.json { render json: @projects, status: 200 } format.xml { render xml: @projects, status: 200 } end end end end
:title end class SongRepresenter < Roar::Decorator include Roar::JSON::JsonApi name :songs ! property :id property :title end https://github.com/apotonick/roar using Mixins using Decorators Roar
:authenticate_or_request ! protected ! def authenticate_or_request authenticate_or_request_with_http_basic do |user, pwd| User.authenticate(user, pwd) end end end end
is limited to API access. • Multiple tokens for each user. • Different access rules can be implemented. API Projects Forum Admin Client A token based auth
:authenticate_or_request ! protected ! def authenticate_or_request authenticate_or_request_with_http_token do |token, opt| User.find_by(auth_token: token) end end end end
Y, feature Z Compatible changes: • addition of a new format (i.e. JSON, XML ) • addition of a new property on a resource • renaming of an end-point (use 3xx status code!) • Only use major version. • Changes cannot break existing clients. • No need to bump version on compatible changes. versioning services
setup { host! 'api.example.com' } ! test 'returns list of projects' do get '/projects' assert_equal 200, response.status refute_empty response.body end end
setup { host! 'api.example.com' } ! test 'returns list of projects' do get '/projects' assert_equal 200, response.status refute_empty response.body end end
'api.example.com' } test 'returns projects in JSON' do get '/projects', {}, { 'Accept' => Mime::JSON } assert_equal Mime::JSON, response.content_type end test 'returns projects in XML' do get '/projects', {}, { 'Accept' => Mime::XML } assert_equal Mime::XML, response.content_type end end
'api.example.com' } test 'returns projects in JSON' do get '/projects', {}, { 'Accept' => Mime::JSON } assert_equal Mime::JSON, response.content_type end test 'returns projects in XML' do get '/projects', {}, { 'Accept' => Mime::XML } assert_equal Mime::XML, response.content_type end end
setup { host! 'api.example.com' } ! test 'valid authentication with token' do get '/projects', {}, { 'Authorization' => "Token token=#{@user.auth_token}"} assert_equal 200, response.status assert_equal Mime::JSON, response.content_type end ! test 'invalid authentication' do get '/projects', {}, { 'Authorization' => "Token token=#{@user.auth_token}fake" } assert_equal 401, response.status end end testing access rules
setup { host! 'api.example.com' } ! test 'valid authentication with token' do get '/projects', {}, { 'Authorization' => "Token token=#{@user.auth_token}"} assert_equal 200, response.status assert_equal Mime::JSON, response.content_type end ! test 'invalid authentication' do get '/projects', {}, { 'Authorization' => "Token token=#{@user.auth_token}fake" } assert_equal 401, response.status end end testing access rules