Skip to content

periodica-press/per_api_struct

 
 

Repository files navigation

ApiStruct consists of two main interfaces: ApiStruct::Client and ApiStruct::Entity. The ApiStruct::Client class is aimed at using the same interface for describing requests to different APIs. The ApiStruct::Entity enables you to use ApiStruct clients in ORM-like style.

Originally from: https://github.com/rubygarage/api_struct

Installation

Add this line to your application's Gemfile:

gem 'per_api_struct', git: 'https://github.com/periodica-press/per_api_struct.git'

And then execute:

$ bundle

Usage

Initialize APIs routes:

ApiStruct::Settings.configure do |config|
  config.endpoints = {
    first_api: {
      root: 'http://localhost:3000/api/v1',
      headers: {
        'content-type': 'application/json',
        'Authorization': 'Bearer TOKEN'
      }
    },
    second_api: {
      root: 'http://localhost:3001/api/v1',
      params: { token: 'Default token' }
    }
  }
end

Client

Endpoint wrapper

class PostsClient < ApiStruct::Client
  first_api :posts

  def show(id)
    get(id)
  end

  def index
    get
  end

  def user_posts(user_id, post_id = nil)
    get(post_id, prefix: [:users, user_id])
    # alias:
    # get(post_id, prefix: '/users/:id', id: user_id)
  end

  def custom_path(user_id)
    get(path: 'users_posts/:user_id', user_id: user_id)
  end
end

Usage:

PostsClient.new.get(1) # -> /posts/1

Returns Result monad

# => Success({:id=>1, :title=>"Post"})

Other methods from sample:

post_client = PostsClient.new

post_client.index            # -> /posts
post_client.user_posts(1)    # -> /users/1/posts
post_client.user_posts(1, 2) # -> /users/1/posts/2
post_client.custom_path(1)   # -> /users_posts/1/

Entity

Response serializer

class User < ApiStruct::Entity
  client_service UsersClient

  client_service AuthorsClient, prefix: true, only: :index
  # alias:
  # client_service AuthorsClient, prefix: :prefix, except: :index

  attr_entity :name, :id
end
class UsersClient < ApiStruct::Client
  first_api :users

  def show(id)
    get(id)
  end
end
class AuthorsClient < ApiStruct::Client
  first_api :authors

  def index
    get
  end
end

Usage:

user = User.show(1)
# => {"id"=>1, "name"=>"John"}

Call methods from prefixed clients:

users = User.authors_client_index
# or
# users = User.prefix_index

Response serializers with related entities:

class Network < ApiStruct::Entity
  client_service NetworkClient

  attr_entity :name, :id
  attr_entity :state, &:to_sym

  has_entity :super_admin, as: User
end
class NetworkClient < ApiStruct::Client
  first_api :networks

  def show(id)
    get(id)
  end
end

Usage:

network = Network.show(1)
# => {"id"=>1, "name"=>"Main network", "state"=>"active", "super_admin"=>{"id"=>1, "name"=>"John"}}

network.state
# => :active

Dynamic headers:

class Auth
  def self.call
    # Get a token..
  end
end
class AuthHeaderValue
  def self.call
    { "Authorization": "Bearer #{Auth.call}" }
  end
end
class PostClient < ApiStruct::Client
  first_api :posts

  def update(id, post_data)
    put(id, json: post_data, headers: AuthHeaderValue.call)
  end
end

About

API wrapper builder with response serialization

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Ruby 99.4%
  • Shell 0.6%