Skip to content

Instantly share code, notes, and snippets.

@janko
Last active March 20, 2016 21:02
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save janko/648a6d434ff1bcee2bad to your computer and use it in GitHub Desktop.
Save janko/648a6d434ff1bcee2bad to your computer and use it in GitHub Desktop.
Yaks demonstration on the local Ruby meetup

API

  • You sometimes need to create an API

    • You want frontend and backend separate
    • You need REST API alongside the web app (GitHub, DNSimple, Travis)
  • JSON API specifications

    • HAL
    • JSON-API (Steve Klabnik & Yehuda Katz)
    • JSON-LD (W3C)
    • Collection+JSON
    • Siren
  • Libraries for generating JSON representations

    • ActiveModel::Serializers (Rails)
    • JSONAPI::Resources (Rails)
    • RABL (Rails)
    • Yaks
require "yaks"
yaks = Yaks.new do
default_format :json_api
end
class User < Struct.new(:first_name, :last_name)
end
class UserMapper < Yaks::Mapper
attributes :first_name, :last_name
end
users = [
User.new("Janko", "Marohnić"),
User.new("Bruno", "Sutić"),
User.new("Zoran", "Majstorović"),
]
puts yaks.call(users)
# {
# "data": [
# {
# "type": "users",
# "first_name": "Janko",
# "last_name": "Marohnić"
# },
# {
# "type": "users",
# "first_name": "Bruno",
# "last_name": "Sutić"
# },
# {
# "type": "users",
# "first_name": "Zoran",
# "last_name": "Majstorović"
# }
# ]
# }
require "yaks"
yaks = Yaks.new do
default_format :json_api
end
class User < Struct.new(:id, :first_name, :last_name)
attr_accessor :posts
end
class UserMapper < Yaks::Mapper
attributes :id, :first_name, :last_name
has_many :posts
end
class Post < Struct.new(:id, :title, :body)
end
class PostMapper < Yaks::Mapper
attributes :id, :title, :body
end
user = User.new(1, "Janko", "Marohnić")
user.posts = [
Post.new(5, "TDD is dead", "Look at me, I'm DHH, I'm on top of the world."),
Post.new(17, "Rails is Omakase", "You can basically cook Rails applications."),
]
puts yaks.call(user)
# {
# "data": {
# "type": "users",
# "id": 1,
# "first_name": "Janko",
# "last_name": "Marohnić",
# "links": {
# "posts": {
# "linkage": [
# {
# "type": "posts",
# "id": 5
# },
# {
# "type": "posts",
# "id": 17
# }
# ]
# }
# }
# },
# "included": [
# {
# "type": "posts",
# "id": 5,
# "title": "TDD is dead",
# "body": "Look at me, I'm DHH, I'm on top of the world."
# },
# {
# "type": "posts",
# "id": 17,
# "title": "Rails is Omakase",
# "body": "You can basically cook Rails applications."
# }
# ]
# }
require "yaks"
require "time"
yaks = Yaks.new do
default_format :json_api
map_to_primitive(Time, Date) { |time| time.iso8601 }
end
class User < Struct.new(:id, :first_name, :last_name, :birthdate)
end
class UserMapper < Yaks::Mapper
attributes :id, :first_name, :last_name, :birthdate
end
user = User.new(1, "Janko", "Marohnić", Date.new(1991, 03, 10))
puts yaks.call(user)
# {
# "data": {
# "type": "users",
# "id": 1,
# "first_name": "Janko",
# "last_name": "Marohnić",
# "birthdate": "1991-03-10"
# }
# }
require "yaks"
require "rack/utils"
yaks = Yaks.new do
default_format :json_api
end
# /user?include=quizzes.questions,gameplays
class BaseMapper < Yaks::Mapper
def self.has_one(name, **options)
super name, **options, if: -> { include_association?(name) }
end
def self.has_many(name, **options)
super name, **options, if: -> { include_association?(name) }
end
private
def include_association?(name)
includes.any? do |relationship|
relationship.split(".")[mapper_stack.size] == name.to_s
end
end
def includes
query = Rack::Utils.parse_query(env["QUERY_STRING"])
query["include"].to_s.split(",")
end
end
class User < Struct.new(:id, :first_name, :last_name)
attr_accessor :posts
end
class UserMapper < BaseMapper
attributes :id, :first_name, :last_name
has_many :posts
end
class Post < Struct.new(:id, :title, :body)
end
class PostMapper < BaseMapper
attributes :id, :title, :body
end
user = User.new(1, "Janko", "Marohnić")
user.posts = [
Post.new(5, "TDD is dead", "Look at me, I'm DHH, I'm on top of the world."),
Post.new(17, "Rails is Omakase", "You can basically cook Rails applications."),
]
env = {"QUERY_STRING" => "include=posts"}
puts yaks.call(user, env: env)
# {
# "data": {
# "type": "users",
# "id": 1,
# "first_name": "Janko",
# "last_name": "Marohnić",
# "links": {
# "posts": {
# "linkage": [
# {
# "type": "posts",
# "id": 5
# },
# {
# "type": "posts",
# "id": 17
# }
# ]
# }
# }
# },
# "included": [
# {
# "type": "posts",
# "id": 5,
# "title": "TDD is dead",
# "body": "Look at me, I'm DHH, I'm on top of the world."
# },
# {
# "type": "posts",
# "id": 17,
# "title": "Rails is Omakase",
# "body": "You can basically cook Rails applications."
# }
# ]
# }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment