SlideShare a Scribd company logo
1 of 62
Download to read offline
Why AMS Adapters, in Rails 5,
are so important to a
wonderful RESTful API
{
"data": {
"type": "Developer",
"id": "Tiago Freire",
"attributes": {
"nickname" : "Kuruma",
"background_knowledge": [ "C", "C++", "C#", "Java"],
"current_language:": "Ruby",
"interest": "Rust"
},
"relationships": {
"jobs": {
"data": { "type": "Software Boutique", "id": "Codeminer42" },
"links": {
"related": {
"href": "http://www.codeminer42.com"
}
}
},
"consultancy": {
"data": { "type": "Host and Cloud services", "id": "Locaweb" },
"links": {
"related": {
"href": "http://www.locaweb.com.br"
}
}
}
}
}
}
{
"data": {
"type": "Developer",
"id": "Bruno Bacarini",
"attributes": {
"nickname" : "bacarini",
"background_knowledge": ["Java"],
"current_language:": "Ruby"
},
"relationships": {
"jobs": [
{ "data": {
"type": "Host and Cloud services",
"id": "Locaweb"
},
"links": {
"related": {
"href": "http://www.locaweb.com.br"
}
}
},{
"data": {
"type": "e-recruitment",
"id": "VAGAS.com"
},
"links": {
"related": {
"href": "http://www.vagas.com.br"
}
}
}]
}
}
}
Developer
Experience
JSON API
Rails 5Rails 5
REST
API
AMS
Hypermedia
Adapters
Patterns
Documentation
GoodGood
ExperienceExperience
MotivationMotivation
DeveloperDeveloper
ExperienceExperience
REST
Representational State Transfer
ProtocolProtocol
HTTPHTTP
The Hypertext Transfer Protocol (HTTP) is a stateless
application-level protocol for distributed, collaborative,
hypertext information systems.
ResourcesResources
Any information that can be named can be a resource: a document
or image, a temporal service (e.g. "today's weather in Los Angeles"), a
collection of other resources, a non-virtual object (e.g. a person), and
so on. In other words, any concept that might be the target of an
author's hypertext reference must fit within the definition of a
resource.
Roy T. Fielding
HTTP verbsHTTP verbs
[C] POST
[R] GET
[U] PUT / PATCH
[D] DELETE
Hypermedia controlHypermedia control
Machines can follow links when they understand the data format and
relationship types.
Roy T. Fielding
So, where are the
links?
Media TypeMedia Type
Content-typeContent-type
andand
AcceptAccept
Collection+JSON
HAL
JSON-LD
SIREN
JSON-API
...
APIsAPIs
RAILS-API
RAILS 5
rails new appname --apirails new appname --api
ActiveModel::
Serializer
#app/controllers
class PostsController < ApplicationController
def index
@posts = Post.all
render json: @posts
end
end
#app/serializers
class PostSerializer < ActiveModel::Serializer
attributes :id, :name, :date
has_many :comments
end
module ActionController
module Serialization
extend ActiveSupport::Concern
include ActionController::Renderers
...
[:_render_option_json, :_render_with_renderer_json].each do |renderer_method|
define_method renderer_method do |resource, options|
options.fetch(:context) { options[:context] = request }
serializable_resource = get_serializer(resource, options)
super(serializable_resource, options)
end
end
...
end
end
Adapters
Steve KlabnikSteve Klabnik
Yehuda KatzYehuda Katz
JsonAPIJsonAPI
==
anti-bikesheddinganti-bikeshedding
weaponweapon
How to use adaptersHow to use adapters
(Specially JsonAPI)?(Specially JsonAPI)?
#controller/action
render json: @posts, adapter: :json_api
#OR
#config/initializer
ActiveModel::Serializer.config.adapter = :json_api
Accept: application/vnd.example[.version].param[+json]
curl -v -H 'Accept:application/vnd.example.v1+json' localhost:3000
ActiveModel::Serializer::Adapter.register(:json_v1, Json)
ActiveModel::Serializer::Adapter.register(:json_v2, JsonApi)
module ActiveModel
class Serializer
class Adapter
....
def self.create(resource, options = {})
override = options.delete(:adapter)
klass = override ? adapter_class(override) : ActiveModel::Serializer.adapter
klass.new(resource, options)
end
...
end
end
end
Creating my ownCreating my own
adapteradapter
module Example
class UsefulAdapter < ActiveModel::Serializer::Adapter
end
end
# Automatically register adapters when subclassing
def self.inherited(subclass)
ActiveModel::Serializer::Adapter.register(subclass.to_s.demodulize, subclass)
end
First optionFirst option
class MyAdapter; end
ActiveModel::Serializer::Adapter.register(:special_adapter, MyAdapter)
Second optionSecond option
Relationships
Included
Pagination
Meta
#app/serializers
class PostSerializer < ActiveModel::Serializer
attributes :id, :title
has_many :comments
has_one :author
end
"data": [{
"type": "posts",
"id": "1",
"attributes": { "title": "JSON API paints my bikeshed!" },
"relationships": {
"author": {
"links": {
"self": "http://example.com/posts/1/relationships/author",
"related": "http://example.com/posts/1/author"
},
"data": { "type": "people", "id": "9" }
},
"comments": {
"links": {
"self": "http://example.com/posts/1/relationships/comments",
"related": "http://example.com/posts/1/comments"
},
"data": [{ "type": "comments", "id": "5" }]
}
},
"links": { "self": "http://example.com/posts/1" }
}],
class PostsController < ApplicationController
def show
@post = Post.find params[:id]
render json: @post, adapter: :json_api, include: ['comments', 'author']
end
end
"included": [{
"type": "people", "id": "9",
"attributes": {
"first-name": "Dan",
"last-name": "Gebhardt",
"twitter": "dgeb"
},
"links": { "self": "http://example.com/people/9" }
}, {
"type": "comments", "id": "5",
"attributes": { "body": "First!" },
"links": { "self": "http://example.com/comments/5" }
}],
Nested AssociationsNested Associations
(JsonAPI adapter)
class PostsController < ApplicationController
def show
@post = Post.find params[:id]
render json: @post, adapter: :json_api, include: [author: [:bio]]
end
end
class PostSerializer < ActiveModel::Serializer
attributes :id, :name
has_many :author
end
class AuthorSerializer < ActiveModel::Serializer
attributes :id, :name
has_one :bio
end
class BioSerializer < ActiveModel::Serializer
attributes :id, :title
belongs_to :author
end
"included": [
{
"id": "1",
"type": "author",
"attributes": {
"name": "bruno"
},
"relationships": {
"bio": {
"data": [
{
"id": "1",
"type": "bio"
}
]
}
}
},
{
"id": "1",
"type": "bio",
"attributes": {
"title": "foobar"
}
},
module ActiveModel
class Serializer
class Adapter
class JsonApi < Adapter
...
def add_links(options)
links = @hash.fetch(:links) { {} }
resources = serializer.instance_variable_get(:@resource)
if is_paginated?(resources)
@hash[:links] = add_pagination_links(links, resources, options)
end
end
def add_pagination_links(links, resources, options)
pagination_links = JsonApi::PaginationLinks.new(resources, options[:context])
.serializable_hash(options)
links.update(pagination_links)
end
def is_paginated?(resource)
resource.respond_to?(:current_page) &&
resource.respond_to?(:total_pages) &&
resource.respond_to?(:size)
end
...
end
end
end
end
"links": {
"self": "http://example.com/posts?page%5Bnumber%5D=3&page%5Bsize%5D=1",
"first": "http://example.com/posts?page%5Bnumber%5D=1&page%5Bsize%5D=1",
"prev": "http://example.com/posts?page%5Bnumber%5D=2&page%5Bsize%5D=1",
"next": "http://example.com/posts?page%5Bnumber%5D=4&page%5Bsize%5D=1",
"last": "http://example.com/posts?page%5Bnumber%5D=10&page%5Bsize%5D=1"
}
class PostsController < ApplicationController
def show
@post = Post.find params[:id]
render json: @post, adapter: :json_api, meta: { "total-pages" => 10 }
end
end
"meta": {
"total-pages": 10
}
{
"data": [{ "type": "posts", "id": "1",
"attributes": { "title": "JSON API paints my bikeshed!" },
"relationships": {
"author": {
"links": {
"self": "http://example.com/posts/1/relationships/author",
"related": "http://example.com/posts/1/author"
},
"data": { "type": "people", "id": "9" }
},
"comments": {
"links": {
"self": "http://example.com/posts/1/relationships/comments",
"related": "http://example.com/posts/1/comments"
},
"data": [{ "type": "comments", "id": "5" }]
}
},
"links": { "self": "http://example.com/posts/1" }
}],
"included": [{
"type": "people", "id": "9",
"attributes": {
"first-name": "Dan",
"last-name": "Gebhardt",
"twitter": "dgeb"
},
"links": { "self": "http://example.com/people/9" }
}, {
"type": "comments", "id": "5",
"attributes": { "body": "First!" },
"links": { "self": "http://example.com/comments/5" }
}],
"links": {
"self": "http://example.com/posts?page%5Bnumber%5D=3&page%5Bsize%5D=1",
"first": "http://example.com/posts?page%5Bnumber%5D=1&page%5Bsize%5D=1",
"prev": "http://example.com/posts?page%5Bnumber%5D=2&page%5Bsize%5D=1",
"next": "http://example.com/posts?page%5Bnumber%5D=4&page%5Bsize%5D=1",
"last": "http://example.com/posts?page%5Bnumber%5D=10&page%5Bsize%5D=1"
},
"meta": {
"total-pages": 10
}
}
Here are the links!Here are the links!
"data": [{
"type": "posts",
"id": "1",
"attributes": { "title": "JSON API paints my bikeshed!" },
"relationships": {
"author": {
"links": {
"self": "http://example.com/posts/1/relationships/author",
"related": "http://example.com/posts/1/author"
},
"data": { "type": "people", "id": "9" }
},
"comments": {
"links": {
"self": "http://example.com/posts/1/relationships/comments",
"related": "http://example.com/posts/1/comments"
},
"data": [{ "type": "comments", "id": "5" }]
}
},
"links": { "self": "http://example.com/posts/1" }
}],
BuuutBuuut there is stillthere is still
a lot of work to do...a lot of work to do...
Deserialization (for both JSON-API and JSON)
Documentation
A better AC/Serializers integration API
Provide better naming for JSON Adapter
Add support to all conventions on JSON-API
Bring Filter back from older version
Russian Doll Cache (use #fetch_multi)
Start handle nested associations
ams =ams = Array.Array.newnew
amsams <<<< hyperlinkshyperlinks
ams << media-type flexibilityams << media-type flexibility
ams << API more attractiveams << API more attractive
ams << API more explorableams << API more explorable
GoodGood
ExperienceExperience
Thank you allThank you all

More Related Content

What's hot

E2 appspresso hands on lab
E2 appspresso hands on labE2 appspresso hands on lab
E2 appspresso hands on lab
NAVER D2
 

What's hot (20)

Specification-Driven Development of REST APIs by Alexander Zinchuk
Specification-Driven Development of REST APIs by Alexander Zinchuk   Specification-Driven Development of REST APIs by Alexander Zinchuk
Specification-Driven Development of REST APIs by Alexander Zinchuk
 
Advanced Json
Advanced JsonAdvanced Json
Advanced Json
 
BruJUG Brussels GraphQL when RESR API is to less - lessons learned
BruJUG Brussels GraphQL when RESR API is to less - lessons learnedBruJUG Brussels GraphQL when RESR API is to less - lessons learned
BruJUG Brussels GraphQL when RESR API is to less - lessons learned
 
Securing WordPress
Securing WordPressSecuring WordPress
Securing WordPress
 
Building sustainable RESTFul services
Building sustainable RESTFul servicesBuilding sustainable RESTFul services
Building sustainable RESTFul services
 
jQuery from the very beginning
jQuery from the very beginningjQuery from the very beginning
jQuery from the very beginning
 
Together Cheerfully to Walk with Hypermedia
Together Cheerfully to Walk with HypermediaTogether Cheerfully to Walk with Hypermedia
Together Cheerfully to Walk with Hypermedia
 
What's Your Problem?
What's Your Problem?What's Your Problem?
What's Your Problem?
 
Agile Testing Days 2018 - API Fundamentals - postman collection
Agile Testing Days 2018 - API Fundamentals - postman collectionAgile Testing Days 2018 - API Fundamentals - postman collection
Agile Testing Days 2018 - API Fundamentals - postman collection
 
HTML 5 & CSS 3
HTML 5 & CSS 3HTML 5 & CSS 3
HTML 5 & CSS 3
 
APIdays Helsinki 2019 - Specification-Driven Development of REST APIs with Al...
APIdays Helsinki 2019 - Specification-Driven Development of REST APIs with Al...APIdays Helsinki 2019 - Specification-Driven Development of REST APIs with Al...
APIdays Helsinki 2019 - Specification-Driven Development of REST APIs with Al...
 
「リモートペアプロでマントルを突き抜けろ!」AWS Cloud9でリモートペアプロ&楽々サーバーレス開発
「リモートペアプロでマントルを突き抜けろ!」AWS Cloud9でリモートペアプロ&楽々サーバーレス開発「リモートペアプロでマントルを突き抜けろ!」AWS Cloud9でリモートペアプロ&楽々サーバーレス開発
「リモートペアプロでマントルを突き抜けろ!」AWS Cloud9でリモートペアプロ&楽々サーバーレス開発
 
Android networking-2
Android networking-2Android networking-2
Android networking-2
 
Plugins unplugged
Plugins unpluggedPlugins unplugged
Plugins unplugged
 
Intro to @viewport & other new Responsive Web Design CSS features
Intro to @viewport & other new Responsive Web Design CSS featuresIntro to @viewport & other new Responsive Web Design CSS features
Intro to @viewport & other new Responsive Web Design CSS features
 
What’s Your Problem?
What’s Your Problem?What’s Your Problem?
What’s Your Problem?
 
E2 appspresso hands on lab
E2 appspresso hands on labE2 appspresso hands on lab
E2 appspresso hands on lab
 
Building Beautiful REST APIs in ASP.NET Core
Building Beautiful REST APIs in ASP.NET CoreBuilding Beautiful REST APIs in ASP.NET Core
Building Beautiful REST APIs in ASP.NET Core
 
Beautiful REST+JSON APIs with Ion
Beautiful REST+JSON APIs with IonBeautiful REST+JSON APIs with Ion
Beautiful REST+JSON APIs with Ion
 
RESTFUL SERVICES MADE EASY: THE EVE REST API FRAMEWORK - Nicola Iarocci - Co...
RESTFUL SERVICES MADE EASY: THE EVE REST API FRAMEWORK -  Nicola Iarocci - Co...RESTFUL SERVICES MADE EASY: THE EVE REST API FRAMEWORK -  Nicola Iarocci - Co...
RESTFUL SERVICES MADE EASY: THE EVE REST API FRAMEWORK - Nicola Iarocci - Co...
 

Viewers also liked

6traits pp
6traits pp6traits pp
6traits pp
btartufo
 
Presentation1
Presentation1Presentation1
Presentation1
mcarroll1
 
History of the Internet
History of the InternetHistory of the Internet
History of the Internet
Bianca_04
 
3 la gramàtica. morf nominal power
3 la gramàtica. morf nominal power3 la gramàtica. morf nominal power
3 la gramàtica. morf nominal power
pilar
 
「INFOGRAPHIC」 The Great 21st Century North American War: Unicorns vs Narwhals
「INFOGRAPHIC」 The Great 21st Century North American War: Unicorns vs Narwhals「INFOGRAPHIC」 The Great 21st Century North American War: Unicorns vs Narwhals
「INFOGRAPHIC」 The Great 21st Century North American War: Unicorns vs Narwhals
domain .ME
 

Viewers also liked (16)

Port Gardner, Everett - March 2014 Newsletter
Port Gardner, Everett - March 2014 NewsletterPort Gardner, Everett - March 2014 Newsletter
Port Gardner, Everett - March 2014 Newsletter
 
6traits pp
6traits pp6traits pp
6traits pp
 
Port Gardner, Everett - October Newsletter
Port Gardner, Everett - October NewsletterPort Gardner, Everett - October Newsletter
Port Gardner, Everett - October Newsletter
 
Port Gardner, Everett - October 2014 Newsletter
Port Gardner, Everett - October 2014 NewsletterPort Gardner, Everett - October 2014 Newsletter
Port Gardner, Everett - October 2014 Newsletter
 
Port Gardner, Everett - May 2014 Newsletter
Port Gardner, Everett - May 2014 NewsletterPort Gardner, Everett - May 2014 Newsletter
Port Gardner, Everett - May 2014 Newsletter
 
Presentation1
Presentation1Presentation1
Presentation1
 
Voic epp
Voic eppVoic epp
Voic epp
 
Internet 2556 แก้ไข
Internet 2556 แก้ไขInternet 2556 แก้ไข
Internet 2556 แก้ไข
 
History of the Internet
History of the InternetHistory of the Internet
History of the Internet
 
Converting in metric
Converting in metricConverting in metric
Converting in metric
 
3 la gramàtica. morf nominal power
3 la gramàtica. morf nominal power3 la gramàtica. morf nominal power
3 la gramàtica. morf nominal power
 
Marketing Findings & Implications
Marketing Findings & ImplicationsMarketing Findings & Implications
Marketing Findings & Implications
 
Thoughts to Consider
Thoughts to ConsiderThoughts to Consider
Thoughts to Consider
 
Marketing Plan Sample
Marketing Plan SampleMarketing Plan Sample
Marketing Plan Sample
 
Thoughts on Paper. Summary of Discussion with Prospect.
Thoughts on Paper. Summary of Discussion with Prospect.Thoughts on Paper. Summary of Discussion with Prospect.
Thoughts on Paper. Summary of Discussion with Prospect.
 
「INFOGRAPHIC」 The Great 21st Century North American War: Unicorns vs Narwhals
「INFOGRAPHIC」 The Great 21st Century North American War: Unicorns vs Narwhals「INFOGRAPHIC」 The Great 21st Century North American War: Unicorns vs Narwhals
「INFOGRAPHIC」 The Great 21st Century North American War: Unicorns vs Narwhals
 

Similar to Ams adapters

Solutions for bi-directional Integration between Oracle RDMBS & Apache Kafka
Solutions for bi-directional Integration between Oracle RDMBS & Apache KafkaSolutions for bi-directional Integration between Oracle RDMBS & Apache Kafka
Solutions for bi-directional Integration between Oracle RDMBS & Apache Kafka
Guido Schmutz
 
Solutions for bi-directional integration between Oracle RDBMS and Apache Kafk...
Solutions for bi-directional integration between Oracle RDBMS and Apache Kafk...Solutions for bi-directional integration between Oracle RDBMS and Apache Kafk...
Solutions for bi-directional integration between Oracle RDBMS and Apache Kafk...
confluent
 
Real-time search in Drupal with Elasticsearch @Moldcamp
Real-time search in Drupal with Elasticsearch @MoldcampReal-time search in Drupal with Elasticsearch @Moldcamp
Real-time search in Drupal with Elasticsearch @Moldcamp
Alexei Gorobets
 
Stratalux Cloud Formation and Chef Integration Presentation
Stratalux Cloud Formation and Chef Integration PresentationStratalux Cloud Formation and Chef Integration Presentation
Stratalux Cloud Formation and Chef Integration Presentation
Jeremy Przygode
 

Similar to Ams adapters (20)

Cdm mil-18 - hypermedia ap is for headless platforms and data integration
Cdm mil-18 - hypermedia ap is for headless platforms and data integrationCdm mil-18 - hypermedia ap is for headless platforms and data integration
Cdm mil-18 - hypermedia ap is for headless platforms and data integration
 
Automatic discovery of Web API Specifications: an example-driven approach
Automatic discovery of Web API Specifications: an example-driven approachAutomatic discovery of Web API Specifications: an example-driven approach
Automatic discovery of Web API Specifications: an example-driven approach
 
Solutions for bi-directional integration between Oracle RDBMS & Apache Kafka
Solutions for bi-directional integration between Oracle RDBMS & Apache KafkaSolutions for bi-directional integration between Oracle RDBMS & Apache Kafka
Solutions for bi-directional integration between Oracle RDBMS & Apache Kafka
 
Solutions for bi-directional Integration between Oracle RDMBS & Apache Kafka
Solutions for bi-directional Integration between Oracle RDMBS & Apache KafkaSolutions for bi-directional Integration between Oracle RDMBS & Apache Kafka
Solutions for bi-directional Integration between Oracle RDMBS & Apache Kafka
 
Solutions for bi-directional integration between Oracle RDBMS and Apache Kafk...
Solutions for bi-directional integration between Oracle RDBMS and Apache Kafk...Solutions for bi-directional integration between Oracle RDBMS and Apache Kafk...
Solutions for bi-directional integration between Oracle RDBMS and Apache Kafk...
 
SDKs, the good the bad the ugly - Japan
SDKs, the good the bad the ugly - JapanSDKs, the good the bad the ugly - Japan
SDKs, the good the bad the ugly - Japan
 
Full-Text Search Explained - Philipp Krenn - Codemotion Rome 2017
Full-Text Search Explained - Philipp Krenn - Codemotion Rome 2017Full-Text Search Explained - Philipp Krenn - Codemotion Rome 2017
Full-Text Search Explained - Philipp Krenn - Codemotion Rome 2017
 
Elastic tire demo
Elastic tire demoElastic tire demo
Elastic tire demo
 
Designing REST API automation tests in Kotlin
Designing REST API automation tests in KotlinDesigning REST API automation tests in Kotlin
Designing REST API automation tests in Kotlin
 
Real-time search in Drupal with Elasticsearch @Moldcamp
Real-time search in Drupal with Elasticsearch @MoldcampReal-time search in Drupal with Elasticsearch @Moldcamp
Real-time search in Drupal with Elasticsearch @Moldcamp
 
Getting into ember.js
Getting into ember.jsGetting into ember.js
Getting into ember.js
 
Building Advanced Serverless Applications
Building Advanced Serverless ApplicationsBuilding Advanced Serverless Applications
Building Advanced Serverless Applications
 
Stratalux Cloud Formation and Chef Integration Presentation
Stratalux Cloud Formation and Chef Integration PresentationStratalux Cloud Formation and Chef Integration Presentation
Stratalux Cloud Formation and Chef Integration Presentation
 
Workshop 17: EmberJS parte II
Workshop 17: EmberJS parte IIWorkshop 17: EmberJS parte II
Workshop 17: EmberJS parte II
 
Use Angular Schematics to Simplify Your Life - Develop Denver 2019
Use Angular Schematics to Simplify Your Life - Develop Denver 2019Use Angular Schematics to Simplify Your Life - Develop Denver 2019
Use Angular Schematics to Simplify Your Life - Develop Denver 2019
 
Document Conversion & Retrieve and Rank 一問一答
Document Conversion & Retrieve and Rank 一問一答Document Conversion & Retrieve and Rank 一問一答
Document Conversion & Retrieve and Rank 一問一答
 
Introduction to GraphQL and AWS Appsync on AWS - iOS
Introduction to GraphQL and AWS Appsync on AWS - iOSIntroduction to GraphQL and AWS Appsync on AWS - iOS
Introduction to GraphQL and AWS Appsync on AWS - iOS
 
Introduction to JavaScript Basics.
Introduction to JavaScript Basics.Introduction to JavaScript Basics.
Introduction to JavaScript Basics.
 
A Gentle Introduction to Angular Schematics - Devoxx Belgium 2019
A Gentle Introduction to Angular Schematics - Devoxx Belgium 2019A Gentle Introduction to Angular Schematics - Devoxx Belgium 2019
A Gentle Introduction to Angular Schematics - Devoxx Belgium 2019
 
Pentesting Modern Web Apps: A Primer
Pentesting Modern Web Apps: A PrimerPentesting Modern Web Apps: A Primer
Pentesting Modern Web Apps: A Primer
 

Recently uploaded

Recently uploaded (20)

Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 
Developing An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilDeveloping An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of Brazil
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 

Ams adapters

  • 1. Why AMS Adapters, in Rails 5, are so important to a wonderful RESTful API
  • 2. { "data": { "type": "Developer", "id": "Tiago Freire", "attributes": { "nickname" : "Kuruma", "background_knowledge": [ "C", "C++", "C#", "Java"], "current_language:": "Ruby", "interest": "Rust" }, "relationships": { "jobs": { "data": { "type": "Software Boutique", "id": "Codeminer42" }, "links": { "related": { "href": "http://www.codeminer42.com" } } }, "consultancy": { "data": { "type": "Host and Cloud services", "id": "Locaweb" }, "links": { "related": { "href": "http://www.locaweb.com.br" } } } } } }
  • 3. { "data": { "type": "Developer", "id": "Bruno Bacarini", "attributes": { "nickname" : "bacarini", "background_knowledge": ["Java"], "current_language:": "Ruby" }, "relationships": { "jobs": [ { "data": { "type": "Host and Cloud services", "id": "Locaweb" }, "links": { "related": { "href": "http://www.locaweb.com.br" } } },{ "data": { "type": "e-recruitment", "id": "VAGAS.com" }, "links": { "related": { "href": "http://www.vagas.com.br" } } }] } } }
  • 4. Developer Experience JSON API Rails 5Rails 5 REST API AMS Hypermedia Adapters Patterns Documentation
  • 9.
  • 10. ProtocolProtocol HTTPHTTP The Hypertext Transfer Protocol (HTTP) is a stateless application-level protocol for distributed, collaborative, hypertext information systems.
  • 11. ResourcesResources Any information that can be named can be a resource: a document or image, a temporal service (e.g. "today's weather in Los Angeles"), a collection of other resources, a non-virtual object (e.g. a person), and so on. In other words, any concept that might be the target of an author's hypertext reference must fit within the definition of a resource. Roy T. Fielding
  • 12. HTTP verbsHTTP verbs [C] POST [R] GET [U] PUT / PATCH [D] DELETE
  • 13. Hypermedia controlHypermedia control Machines can follow links when they understand the data format and relationship types. Roy T. Fielding
  • 14. So, where are the links?
  • 15.
  • 19.
  • 22.
  • 24.
  • 25. rails new appname --apirails new appname --api
  • 27. #app/controllers class PostsController < ApplicationController def index @posts = Post.all render json: @posts end end #app/serializers class PostSerializer < ActiveModel::Serializer attributes :id, :name, :date has_many :comments end
  • 28. module ActionController module Serialization extend ActiveSupport::Concern include ActionController::Renderers ... [:_render_option_json, :_render_with_renderer_json].each do |renderer_method| define_method renderer_method do |resource, options| options.fetch(:context) { options[:context] = request } serializable_resource = get_serializer(resource, options) super(serializable_resource, options) end end ... end end
  • 30.
  • 31.
  • 34. How to use adaptersHow to use adapters (Specially JsonAPI)?(Specially JsonAPI)?
  • 35. #controller/action render json: @posts, adapter: :json_api #OR #config/initializer ActiveModel::Serializer.config.adapter = :json_api
  • 36.
  • 37. Accept: application/vnd.example[.version].param[+json] curl -v -H 'Accept:application/vnd.example.v1+json' localhost:3000 ActiveModel::Serializer::Adapter.register(:json_v1, Json) ActiveModel::Serializer::Adapter.register(:json_v2, JsonApi)
  • 38. module ActiveModel class Serializer class Adapter .... def self.create(resource, options = {}) override = options.delete(:adapter) klass = override ? adapter_class(override) : ActiveModel::Serializer.adapter klass.new(resource, options) end ... end end end
  • 39. Creating my ownCreating my own adapteradapter
  • 40. module Example class UsefulAdapter < ActiveModel::Serializer::Adapter end end # Automatically register adapters when subclassing def self.inherited(subclass) ActiveModel::Serializer::Adapter.register(subclass.to_s.demodulize, subclass) end First optionFirst option
  • 43. #app/serializers class PostSerializer < ActiveModel::Serializer attributes :id, :title has_many :comments has_one :author end
  • 44. "data": [{ "type": "posts", "id": "1", "attributes": { "title": "JSON API paints my bikeshed!" }, "relationships": { "author": { "links": { "self": "http://example.com/posts/1/relationships/author", "related": "http://example.com/posts/1/author" }, "data": { "type": "people", "id": "9" } }, "comments": { "links": { "self": "http://example.com/posts/1/relationships/comments", "related": "http://example.com/posts/1/comments" }, "data": [{ "type": "comments", "id": "5" }] } }, "links": { "self": "http://example.com/posts/1" } }],
  • 45. class PostsController < ApplicationController def show @post = Post.find params[:id] render json: @post, adapter: :json_api, include: ['comments', 'author'] end end
  • 46. "included": [{ "type": "people", "id": "9", "attributes": { "first-name": "Dan", "last-name": "Gebhardt", "twitter": "dgeb" }, "links": { "self": "http://example.com/people/9" } }, { "type": "comments", "id": "5", "attributes": { "body": "First!" }, "links": { "self": "http://example.com/comments/5" } }],
  • 48. class PostsController < ApplicationController def show @post = Post.find params[:id] render json: @post, adapter: :json_api, include: [author: [:bio]] end end class PostSerializer < ActiveModel::Serializer attributes :id, :name has_many :author end class AuthorSerializer < ActiveModel::Serializer attributes :id, :name has_one :bio end class BioSerializer < ActiveModel::Serializer attributes :id, :title belongs_to :author end
  • 49. "included": [ { "id": "1", "type": "author", "attributes": { "name": "bruno" }, "relationships": { "bio": { "data": [ { "id": "1", "type": "bio" } ] } } }, { "id": "1", "type": "bio", "attributes": { "title": "foobar" } },
  • 50. module ActiveModel class Serializer class Adapter class JsonApi < Adapter ... def add_links(options) links = @hash.fetch(:links) { {} } resources = serializer.instance_variable_get(:@resource) if is_paginated?(resources) @hash[:links] = add_pagination_links(links, resources, options) end end def add_pagination_links(links, resources, options) pagination_links = JsonApi::PaginationLinks.new(resources, options[:context]) .serializable_hash(options) links.update(pagination_links) end def is_paginated?(resource) resource.respond_to?(:current_page) && resource.respond_to?(:total_pages) && resource.respond_to?(:size) end ... end end end end
  • 51.
  • 52.
  • 53. "links": { "self": "http://example.com/posts?page%5Bnumber%5D=3&page%5Bsize%5D=1", "first": "http://example.com/posts?page%5Bnumber%5D=1&page%5Bsize%5D=1", "prev": "http://example.com/posts?page%5Bnumber%5D=2&page%5Bsize%5D=1", "next": "http://example.com/posts?page%5Bnumber%5D=4&page%5Bsize%5D=1", "last": "http://example.com/posts?page%5Bnumber%5D=10&page%5Bsize%5D=1" }
  • 54. class PostsController < ApplicationController def show @post = Post.find params[:id] render json: @post, adapter: :json_api, meta: { "total-pages" => 10 } end end "meta": { "total-pages": 10 }
  • 55. { "data": [{ "type": "posts", "id": "1", "attributes": { "title": "JSON API paints my bikeshed!" }, "relationships": { "author": { "links": { "self": "http://example.com/posts/1/relationships/author", "related": "http://example.com/posts/1/author" }, "data": { "type": "people", "id": "9" } }, "comments": { "links": { "self": "http://example.com/posts/1/relationships/comments", "related": "http://example.com/posts/1/comments" }, "data": [{ "type": "comments", "id": "5" }] } }, "links": { "self": "http://example.com/posts/1" } }], "included": [{ "type": "people", "id": "9", "attributes": { "first-name": "Dan", "last-name": "Gebhardt", "twitter": "dgeb" }, "links": { "self": "http://example.com/people/9" } }, { "type": "comments", "id": "5", "attributes": { "body": "First!" }, "links": { "self": "http://example.com/comments/5" } }], "links": { "self": "http://example.com/posts?page%5Bnumber%5D=3&page%5Bsize%5D=1", "first": "http://example.com/posts?page%5Bnumber%5D=1&page%5Bsize%5D=1", "prev": "http://example.com/posts?page%5Bnumber%5D=2&page%5Bsize%5D=1", "next": "http://example.com/posts?page%5Bnumber%5D=4&page%5Bsize%5D=1", "last": "http://example.com/posts?page%5Bnumber%5D=10&page%5Bsize%5D=1" }, "meta": { "total-pages": 10 } }
  • 56. Here are the links!Here are the links! "data": [{ "type": "posts", "id": "1", "attributes": { "title": "JSON API paints my bikeshed!" }, "relationships": { "author": { "links": { "self": "http://example.com/posts/1/relationships/author", "related": "http://example.com/posts/1/author" }, "data": { "type": "people", "id": "9" } }, "comments": { "links": { "self": "http://example.com/posts/1/relationships/comments", "related": "http://example.com/posts/1/comments" }, "data": [{ "type": "comments", "id": "5" }] } }, "links": { "self": "http://example.com/posts/1" } }],
  • 57. BuuutBuuut there is stillthere is still a lot of work to do...a lot of work to do...
  • 58. Deserialization (for both JSON-API and JSON) Documentation A better AC/Serializers integration API Provide better naming for JSON Adapter Add support to all conventions on JSON-API Bring Filter back from older version Russian Doll Cache (use #fetch_multi) Start handle nested associations
  • 59. ams =ams = Array.Array.newnew amsams <<<< hyperlinkshyperlinks ams << media-type flexibilityams << media-type flexibility ams << API more attractiveams << API more attractive ams << API more explorableams << API more explorable
  • 60.