Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/kyrylo/resource_set
Resource Set provides tools to aid in making API Clients. Such as URL resolving, Request / Response layer, and more. Fork of unmaintained https://github.com/digitalocean/resource_kit
https://github.com/kyrylo/resource_set
Last synced: 9 days ago
JSON representation
Resource Set provides tools to aid in making API Clients. Such as URL resolving, Request / Response layer, and more. Fork of unmaintained https://github.com/digitalocean/resource_kit
- Host: GitHub
- URL: https://github.com/kyrylo/resource_set
- Owner: kyrylo
- License: mit
- Created: 2017-09-07T20:29:00.000Z (over 7 years ago)
- Default Branch: master
- Last Pushed: 2018-04-10T14:18:33.000Z (almost 7 years ago)
- Last Synced: 2025-01-02T16:11:41.483Z (18 days ago)
- Language: Ruby
- Size: 85.9 KB
- Stars: 0
- Watchers: 3
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE.txt
Awesome Lists containing this project
README
# Resource Set
Resource Set provides tools to aid in making API Clients. Such as URL resolving, Request / Response layer, and more.
## Installation
Add this line to your application's Gemfile:
gem 'resource_set'
And then execute:
$ bundle
Or install it yourself as:
$ gem install resource_set
## Usage
This library recommends using [Cartograph](http://github.com/kyrylo/cartograph) for representing and deserializing response bodies.
You'll see it in the examples provided below.### Resource classes
Resource Set provides a comprehensive but intuitive DSL where you describe the remote resources capabilities.
For example, where can I get a list of users? Where do I get a single user? How do I create a user?When you're able to answer these questions, you can describe them in your resource class like this:
```ruby
class DropletResource < ResourceSet::Resource
resources do
default_handler(422) { |response| ErrorMapping.extract_single(response.body, :read) }
default_handler(:ok, :created) { |response| DropletMapping.extract_single(response.body, :read) }
default_handler { |response| raise "Unexpected response status #{response.status}... #{response.body}" }# Defining actions will create instance methods on the resource class to call them.
action :find do
verb :get # get is assumed if this is omitted
path '/droplets/:id'
handler(200) { |response| DropletMapping.extract_single(response.body, :read) }
endaction :all do
path '/droplets'
handler(200) { |body| DropletMapping.extract_collection(body, :read) }
endaction :create do
path '/droplets'
verb :post
body { |object| DropletMapping.representation_for(:create, object) } # Generate a response body from a passed object
handler(202) { |response| DropletMapping.extract_single(response.body, :read) }
end
end
end
```You also have the option to use a shorter version to describe actions like this:
```ruby
class DropletResource < ResourceSet::Resource
resources do
action :all, 'GET /v2/droplets' do
handler(:ok) { |response| DropletMapping.extract_collection(response.body, :read) }
end
end
end
```Instead of using `#action`, you can use any of the supported HTTP verb methods including `#get`, `#post`, `#put`, `#delete`, `#head`, `#patch`, and `#options`. Thus, the above example can be also written as:
```ruby
class DropletResource < ResourceSet::Resource
resources do
get :all, '/v2/droplets' do
handler(:ok) { |response| DropletMapping.extract_collection(response.body, :read) }
end
end
end
```Now that we've described our resources. We can instantiate our class with a connection object. ResourceSet relies on the interface that Faraday provides. For example:
```ruby
conn = Faraday.new(url: 'http://api.digitalocean.com') do |req|
req.adapter :net_http
endresource = DropletResource.new(connection: conn)
```Now that we've instantiated a resource with our class, we can call the actions we've defined on it.
```
all_droplets = resource.all
single_droplet = resource.find(id: 123)
create = resource.create(Droplet.new)
```## Scope
ResourceSet classes give you the option to pass in an optional scope object, so that you may interact with the resource with it that way.
For example, you may want to use this for nested resources:
```ruby
class CommentResource < ResourceSet::Resource
resources do
action :all do
path { "/users/#{user_id}/comments" }
handler(200) { |resp| CommentMapping.extract_collection(resp.body, :read) }
end
enddef user_id
scope.user_id
end
enduser = User.find(123)
resource = CommentResource.new(connection: conn, scope: user)
comments = resource.all #=> Will fetch from /users/123/comments
```## Test Helpers
ResourceSet supplys test helpers that assist in certain things you'd want your resource classes to do.
Make sure you:
require 'resource_set/testing'
Testing a certain action:
```ruby
# Tag the spec with resource_set to bring in the helpers
RSpec.describe MyResourceClass, resource_set: true do
it 'has an all action' do
expect(MyResourceClass).to have_action(:all).that_handles(:ok, :no_content).at_path('/users')
endit 'handles a 201 with response body' do
expect(MyResourceClass).to handle_response(:create).with(status: 201, body: '{"users":[]}') do |handled|
expect(handled).to all(be_kind_of(User))
end
end
end
```### Nice to have's
Things we've thought about but just haven't implemented are:
* Pagination capabilities
## Contributing
1. Fork it ( https://github.com/kyrylo/resource_set/fork )
2. Create your feature branch (`git checkout -b my-new-feature`)
3. Commit your changes (`git commit -am 'Add some feature'`)
4. Push to the branch (`git push origin my-new-feature`)
5. Create a new Pull Request