API INTEGRATIONS
(FOR THE EXCESSIVELY PARANOID)
@ALXJRVS
API Integrations
MAKE ME
SUPER PARANOID
Your Code
Your Code
API INTEGRATIONS IN PLAIN RUBY
token = "Slack Token"
message_query = {
query: {
token: token,
message: "message",
channel: "channel ID"
}
}
message_response = HTTParty.get("https://slack.com/api/chat.postMessage")
list_query = {
query: {
token: token
}
}
list_response = HTTParty.get("https://slack.com/api/channel.list")
1. Get relevant Data from our app
token = "Slack Token"
message_query = {
query: {
token: token,
message: "message",
channel: "channel ID"
}
}
message_response = HTTParty.get("https://slack.com/api/chat.postMessage")
list_query = {
query: {
token: token
}
}
list_response = HTTParty.get("https://slack.com/api/channel.list")
2. Arrange that data into API-friendly parameters
token = "Slack Token"
message_query = {
query: {
token: token,
message: "message",
channel: "channel ID"
}
}
message_response = HTTParty.get("https://slack.com/api/chat.postMessage")
list_query = {
query: {
token: token
}
}
list_response = HTTParty.get("https://slack.com/api/channel.list")
3. Execute the HTTP CALL
token = "Slack Token"
message_query = {
query: {
token: token,
message: "message",
channel: "channel ID"
}
}
message_response = HTTParty.get("https://slack.com/api/chat.postMessage")
list_query = {
query: {
token: token
}
}
list_response = HTTParty.get("https://slack.com/api/channel.list")
4. USE THE RESULTS IN OUR code
token = "Slack Token"
message_query = {
query: {
token: token,
message: "message",
channel: "channel ID"
}
}
message_response = HTTParty.get("https://slack.com/api/chat.postMessage")
list_query = {
query: {
token: token
}
}
list_response = HTTParty.get("https://slack.com/api/channel.list")
Service Objects!
class SlackService
BASE = 'https://slack.com/api'
def initialize(token)
@token
end
def send_message(message:, to:)
query = {
query: {
token: @token,
message: message,
channel: to
}
}
HTTParty.get(BASE + "/chat.postMessage")
end
def channels_list
query = {
query: {
token: @token
}
}
HTTParty.get(BASE + "/channels.list")
end
end
TEsting?
Stub!
Mock!
VCR!
Service Object
VCR Cassette
YOUR CODE
ANALYTICS
API
PAYMENTS
API
SOCIAL
API
DATA
API
YOUR CODE
DISORDER
ANARCHY
CHAOS
PAIN
YOUR CODE
their API
Airlocks
Make
Great
API
Integrations
pattern
A Service
A wrapper
a fake
A Service
class Slack
@@api = SlackApi
cattr_accessor :api
def initialize(token)
@token = token
end
def send(message:, to:)
query = {
query: {
token: token,
channel: to,
message: message
}
}
api.chat_post_message query
end
def list_channels
query = {
query: {
token: token
}
}
api.channels_list query
end
private
attr_reader :token
end
Service: Interface to the API
@@api = SlackApi
cattr_accessor :api
A WRAPPER
class SlackApi
include HTTParty
base_uri 'https://slack.com/api'
CHANNEL_LIST = "/channels.list"
CHAT_POST_MESSAGE = "/chat.postMessage"
def self.chat_post_message(data)
get CHAT_POST_MESSAGE, data
end
def self.channels_list(data)
get CHANNEL_LIST, data
end
end
Wrapper: Thin wrapper over HTTP calls
A FAKE
class SlackApiFake
DEFAULT_FAIL = {"ok"=>false, "error"=>"not_authed"}
@@fail = false
def self.chat_post_message(data)
if @@fail
DEFAULT_FAIL
else
{...}
end
end
def self.channels_list(data)
if @@fail
DEFAULT_FAIL
else
{
"ok" => true,
"channels" => [
{...}
}
]
}
end
end
def self.fail!
@@fail = true
end
def self.reset!
@@fail = false
end
end
Fake: a data formatter
Testing!
UNit test the Service
VCR the wrapper
Maintain the fake
UNIT TEST THE Service
@@api = SlackApi
cattr_accessor :api
Slack.api = SlackFake
VCR THE WRAPPER
Maintain the fake
!=
YOUR CODE
conclusions
integrations should contain as little domain truth as possible
API's are just other people's code
API INTEGRATIONS
By Alex Jarvis
API INTEGRATIONS
for the paranoid
- 802