api-blueprint 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +62 -0
- data/Rakefile +33 -0
- data/lib/api-blueprint.rb +21 -0
- data/lib/api-blueprint/blueprint.rb +69 -0
- data/lib/api-blueprint/builder.rb +39 -0
- data/lib/api-blueprint/cache.rb +26 -0
- data/lib/api-blueprint/collection.rb +24 -0
- data/lib/api-blueprint/model.rb +39 -0
- data/lib/api-blueprint/parser.rb +11 -0
- data/lib/api-blueprint/runner.rb +50 -0
- data/lib/api-blueprint/types.rb +3 -0
- data/lib/api-blueprint/url.rb +30 -0
- data/lib/api-blueprint/version.rb +3 -0
- metadata +256 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: '0809cc6a8a9bb3e101463e557f3e089f8ad14ea4'
|
4
|
+
data.tar.gz: f52e26b878dcf30e2378409e52321709333181b1
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: be379d505c900cc5d725bc7b67765dde33869a119c29a95dfad39ad986e96711dace8136ccfb05e399f4bb22399e085b54f65d5da67a0f0918fcd00aad9e02e2
|
7
|
+
data.tar.gz: e5d97a944496d8a0255c3489ccb7417f3c5bef1e96b45b80c4617ff1b4c42ba58f20ba338f6ea4cc698a827840d280d7a19c64efc697952903db1e11a29805e3
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2018 Damien
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
# ApiBlueprint
|
2
|
+
|
3
|
+
ApiBlueprint is a simple wrapper designed to be used in a Rails app for running http requests through Faraday and generating strongly-typed models from the JSON responses.
|
4
|
+
|
5
|
+
## Example use
|
6
|
+
|
7
|
+
The examples below use the [open notify astros](http://api.open-notify.org/astros.json) api endpoint to list the astronauts who are current in space and which craft they are on.
|
8
|
+
|
9
|
+
### Blueprints in models
|
10
|
+
|
11
|
+
Using ApiBlueprint::Model, you can define model classes with [dry-types attributes](http://dry-rb.org/gems/dry-types/) and define blueprints which describe how an api call will be made.
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
# app/models/person.rb
|
15
|
+
class Person < ApiBlueprint::Model
|
16
|
+
attribute :name, Types::String
|
17
|
+
attribute :craft, Types::String
|
18
|
+
end
|
19
|
+
|
20
|
+
# app/models/astronauts_in_space.rb
|
21
|
+
class AstronautsInSpace < ApiBlueprint::Model
|
22
|
+
attribute :number, Types::Integer
|
23
|
+
attribute :people, Types::Array.of(Types.Constructor(Person))
|
24
|
+
|
25
|
+
def self.fetch
|
26
|
+
blueprint :get, "http://api.open-notify.org/astros.json"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
```
|
30
|
+
|
31
|
+
### Running blueprints
|
32
|
+
|
33
|
+
Blueprints can be run from controllers using an instance of `ApiBlueprint::Runner`. You can use that runner instance to store session based information such as Authorization headers and such which need to be passed into requests.
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
# app/controllers/application_controller.rb
|
37
|
+
class ApplicationController < ActionController::Base
|
38
|
+
def api
|
39
|
+
ApiBlueprint::Runner.new headers: { Authorization: "something" }
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# app/controllers/astronauts_controller.rb
|
44
|
+
class AstronautsController < ApplicationController
|
45
|
+
def index
|
46
|
+
@astronauts = api.run AstronautsInSpace.fetch
|
47
|
+
end
|
48
|
+
end
|
49
|
+
```
|
50
|
+
|
51
|
+
The result of using `api.run` on a blueprint is as you'd expect, nice model instances with the attributes set:
|
52
|
+
|
53
|
+
```erb
|
54
|
+
<!-- app/views/astronauts/index.html.erb -->
|
55
|
+
<h1>There are <%= @astronauts.number %> astronauts in space currently:</h1>
|
56
|
+
|
57
|
+
<ul>
|
58
|
+
<% @astronauts.each do |astronaut| %>
|
59
|
+
<li><%= astronaut.name %> is on <%= astronaut.craft %></li>
|
60
|
+
<% end %>
|
61
|
+
</ul>
|
62
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
begin
|
2
|
+
require 'bundler/setup'
|
3
|
+
rescue LoadError
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'rdoc/task'
|
8
|
+
|
9
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
10
|
+
rdoc.rdoc_dir = 'rdoc'
|
11
|
+
rdoc.title = 'ApiBlueprint'
|
12
|
+
rdoc.options << '--line-numbers'
|
13
|
+
rdoc.rdoc_files.include('README.md')
|
14
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
|
20
|
+
|
21
|
+
|
22
|
+
require 'bundler/gem_tasks'
|
23
|
+
|
24
|
+
require 'rake/testtask'
|
25
|
+
|
26
|
+
Rake::TestTask.new(:test) do |t|
|
27
|
+
t.libs << 'test'
|
28
|
+
t.pattern = 'test/**/*_test.rb'
|
29
|
+
t.verbose = false
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
task default: :test
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'dry-types'
|
2
|
+
require 'dry-struct'
|
3
|
+
require 'dry-initializer'
|
4
|
+
require 'faraday'
|
5
|
+
require 'faraday_middleware'
|
6
|
+
require 'active_model'
|
7
|
+
require 'addressable'
|
8
|
+
|
9
|
+
require 'api-blueprint/cache'
|
10
|
+
require 'api-blueprint/types'
|
11
|
+
require 'api-blueprint/url'
|
12
|
+
require 'api-blueprint/parser'
|
13
|
+
require 'api-blueprint/builder'
|
14
|
+
require 'api-blueprint/model'
|
15
|
+
require 'api-blueprint/blueprint'
|
16
|
+
require 'api-blueprint/runner'
|
17
|
+
require 'api-blueprint/collection'
|
18
|
+
|
19
|
+
module ApiBlueprint
|
20
|
+
class DefinitionError < StandardError; end
|
21
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module ApiBlueprint
|
2
|
+
class Blueprint < Dry::Struct
|
3
|
+
constructor_type :schema
|
4
|
+
|
5
|
+
attribute :http_method, Types::Symbol.default(:get).enum(*Faraday::Connection::METHODS)
|
6
|
+
attribute :url, Types::String
|
7
|
+
attribute :headers, Types::Hash.default(Hash.new)
|
8
|
+
attribute :params, Types::Hash.default(Hash.new)
|
9
|
+
attribute :body, Types::Hash.default(Hash.new)
|
10
|
+
attribute :creates, Types::Any
|
11
|
+
attribute :parser, Types.Instance(ApiBlueprint::Parser).default(ApiBlueprint::Parser.new)
|
12
|
+
attribute :replacements, Types::Hash.default(Hash.new)
|
13
|
+
attribute :after_build, Types::Instance(Proc).optional
|
14
|
+
attribute :builder, Types.Instance(ApiBlueprint::Builder).default(ApiBlueprint::Builder.new)
|
15
|
+
|
16
|
+
def all_request_options(options = {})
|
17
|
+
{
|
18
|
+
http_method: http_method,
|
19
|
+
url: url,
|
20
|
+
headers: headers.merge(options.fetch(:headers, {})),
|
21
|
+
params: params.merge(options.fetch(:params, {})),
|
22
|
+
body: body.merge(options.fetch(:body, {}))
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
def run(options = {}, runner = nil)
|
27
|
+
response = call_api all_request_options(options)
|
28
|
+
|
29
|
+
if creates.present?
|
30
|
+
builder_options = {
|
31
|
+
body: parser.parse(response.body),
|
32
|
+
headers: response.headers,
|
33
|
+
replacements: replacements,
|
34
|
+
creates: creates
|
35
|
+
}
|
36
|
+
|
37
|
+
created = builder.new(builder_options).build
|
38
|
+
else
|
39
|
+
created = response
|
40
|
+
end
|
41
|
+
|
42
|
+
after_build.present? ? after_build.call(runner, created) : created
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def call_api(options)
|
48
|
+
connection.send options[:http_method] do |req|
|
49
|
+
req.url options[:url]
|
50
|
+
req.headers.merge! options[:headers]
|
51
|
+
req.params = options[:params]
|
52
|
+
req.body = options[:body].to_json
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def connection
|
57
|
+
Faraday.new do |conn|
|
58
|
+
conn.response :json, content_type: /\bjson$/
|
59
|
+
# conn.response :logger
|
60
|
+
|
61
|
+
conn.adapter Faraday.default_adapter
|
62
|
+
conn.headers = {
|
63
|
+
"User-Agent": "ApiBlueprint"
|
64
|
+
}
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module ApiBlueprint
|
2
|
+
class Builder < Dry::Struct
|
3
|
+
constructor_type :schema
|
4
|
+
|
5
|
+
attribute :body, Types::Hash.default(Hash.new)
|
6
|
+
attribute :headers, Types::Hash.default(Hash.new)
|
7
|
+
attribute :replacements, Types::Hash.default(Hash.new)
|
8
|
+
attribute :creates, Types::Any
|
9
|
+
|
10
|
+
attr_writer :body
|
11
|
+
|
12
|
+
def build
|
13
|
+
if body.is_a? Array
|
14
|
+
body.collect { |item| build_item prepare_item(item) }
|
15
|
+
else
|
16
|
+
build_item prepare_item(body)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def prepare_item(item)
|
21
|
+
with_replacements item.with_indifferent_access
|
22
|
+
end
|
23
|
+
|
24
|
+
def build_item(item)
|
25
|
+
creates.new item
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def with_replacements(item)
|
31
|
+
item.tap do |item|
|
32
|
+
replacements.each do |bad, good|
|
33
|
+
item[good] = item.delete bad if item.has_key? bad
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module ApiBlueprint
|
2
|
+
class Cache
|
3
|
+
extend Dry::Initializer
|
4
|
+
|
5
|
+
option :key
|
6
|
+
|
7
|
+
def exist?(id)
|
8
|
+
false
|
9
|
+
end
|
10
|
+
|
11
|
+
def read(id)
|
12
|
+
false
|
13
|
+
end
|
14
|
+
|
15
|
+
def write(id, data, options)
|
16
|
+
data
|
17
|
+
end
|
18
|
+
|
19
|
+
def generate_cache_key(options)
|
20
|
+
options = options.clone.except :body
|
21
|
+
options_digest = Digest::MD5.hexdigest Marshal::dump(options.to_s.chars.sort.join)
|
22
|
+
"#{key}:#{options_digest}"
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module ApiBlueprint
|
2
|
+
class Collection
|
3
|
+
|
4
|
+
attr_reader :blueprints, :creates
|
5
|
+
|
6
|
+
def initialize(blueprints, creates = nil)
|
7
|
+
unless blueprints.is_a?(Hash)
|
8
|
+
raise DefinitionError, "a collection of blueprints must be a hash"
|
9
|
+
end
|
10
|
+
|
11
|
+
unless blueprints.values.all? { |bp| bp.is_a? Blueprint }
|
12
|
+
raise DefinitionError, "all collection values must be blueprints"
|
13
|
+
end
|
14
|
+
|
15
|
+
@blueprints = blueprints
|
16
|
+
@creates = creates
|
17
|
+
end
|
18
|
+
|
19
|
+
def create(args)
|
20
|
+
creates.present? ? creates.new(args) : args
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module ApiBlueprint
|
2
|
+
class Model < Dry::Struct
|
3
|
+
extend Dry::Configurable
|
4
|
+
include ActiveModel::Conversion
|
5
|
+
include ActiveModel::Validations
|
6
|
+
include ActiveModel::Serialization
|
7
|
+
extend ActiveModel::Naming
|
8
|
+
extend ActiveModel::Callbacks
|
9
|
+
|
10
|
+
constructor_type :schema
|
11
|
+
|
12
|
+
setting :host, ""
|
13
|
+
setting :parser, Parser.new
|
14
|
+
setting :builder, Builder.new
|
15
|
+
setting :replacements, {}
|
16
|
+
|
17
|
+
def self.blueprint(http_method, url, options = {}, &block)
|
18
|
+
blueprint_opts = {
|
19
|
+
http_method: http_method,
|
20
|
+
url: Url.new(config.host, url).to_s,
|
21
|
+
creates: self,
|
22
|
+
parser: config.parser,
|
23
|
+
replacements: config.replacements,
|
24
|
+
builder: config.builder
|
25
|
+
}.merge(options)
|
26
|
+
|
27
|
+
if block_given?
|
28
|
+
blueprint_opts[:after_build] = block
|
29
|
+
end
|
30
|
+
|
31
|
+
Blueprint.new blueprint_opts
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.collection(blueprints)
|
35
|
+
Collection.new blueprints, self
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module ApiBlueprint
|
2
|
+
class Runner
|
3
|
+
extend Dry::Initializer
|
4
|
+
|
5
|
+
option :headers, default: proc { {} }
|
6
|
+
option :cache, default: proc { Cache.new key: "global" }
|
7
|
+
|
8
|
+
def run(item, cache_options = {})
|
9
|
+
if item.is_a?(Blueprint)
|
10
|
+
run_blueprint item, cache_options
|
11
|
+
elsif item.is_a?(Collection)
|
12
|
+
run_collection item, cache_options
|
13
|
+
else
|
14
|
+
raise ArgumentError, "expected a blueprint or blueprint collection, got #{item.class}"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def runner_options
|
19
|
+
{ headers: headers, cache: cache }
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def run_blueprint(blueprint, cache_options)
|
25
|
+
request_options = blueprint.all_request_options(runner_options)
|
26
|
+
|
27
|
+
if cache.present?
|
28
|
+
cache_key = cache.generate_cache_key request_options
|
29
|
+
return cache.read cache_key if cache.exist? cache_key
|
30
|
+
end
|
31
|
+
|
32
|
+
blueprint.run(runner_options, self).tap do |result|
|
33
|
+
if cache.present?
|
34
|
+
cache_key = cache.generate_cache_key request_options
|
35
|
+
cache.write cache_key, result, cache_options
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def run_collection(collection, cache_options)
|
41
|
+
args = {}
|
42
|
+
collection.blueprints.each do |name, blueprint|
|
43
|
+
args[name] = run_blueprint blueprint, cache_options
|
44
|
+
end
|
45
|
+
|
46
|
+
collection.create args
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module ApiBlueprint
|
2
|
+
class Url
|
3
|
+
attr_reader :base, :custom
|
4
|
+
|
5
|
+
def initialize(base = "", custom = "")
|
6
|
+
self.base = base
|
7
|
+
self.custom = custom
|
8
|
+
end
|
9
|
+
|
10
|
+
def base=(str)
|
11
|
+
@base = Addressable::URI.parse str
|
12
|
+
end
|
13
|
+
|
14
|
+
def custom=(str)
|
15
|
+
@custom = Addressable::URI.parse str
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_s
|
19
|
+
if base.path.present? && custom.path.present? && !custom.host.present?
|
20
|
+
# Join paths in a permissive way which handles extra slashes gracefully and returns
|
21
|
+
# a string which Addressable can handle when joining with other paths
|
22
|
+
paths = [base.path, custom.path].compact.map { |path| path.gsub(%r{^/*(.*?)/*$}, '\1') }.join("/")
|
23
|
+
Addressable::URI.join(base.site, paths).to_s
|
24
|
+
else
|
25
|
+
base.join(custom).to_s
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
metadata
ADDED
@@ -0,0 +1,256 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: api-blueprint
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Damien Timewell
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-04-06 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: dry-types
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: dry-struct
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: dry-initializer
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: dry-configurable
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: faraday
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: faraday_middleware
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: activemodel
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: addressable
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: rails
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: 5.1.5
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: 5.1.5
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: sqlite3
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: pry
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - ">="
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0'
|
160
|
+
type: :development
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - ">="
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '0'
|
167
|
+
- !ruby/object:Gem::Dependency
|
168
|
+
name: rspec
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - ">="
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0'
|
174
|
+
type: :development
|
175
|
+
prerelease: false
|
176
|
+
version_requirements: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - ">="
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: '0'
|
181
|
+
- !ruby/object:Gem::Dependency
|
182
|
+
name: webmock
|
183
|
+
requirement: !ruby/object:Gem::Requirement
|
184
|
+
requirements:
|
185
|
+
- - ">="
|
186
|
+
- !ruby/object:Gem::Version
|
187
|
+
version: '0'
|
188
|
+
type: :development
|
189
|
+
prerelease: false
|
190
|
+
version_requirements: !ruby/object:Gem::Requirement
|
191
|
+
requirements:
|
192
|
+
- - ">="
|
193
|
+
- !ruby/object:Gem::Version
|
194
|
+
version: '0'
|
195
|
+
- !ruby/object:Gem::Dependency
|
196
|
+
name: guard-rspec
|
197
|
+
requirement: !ruby/object:Gem::Requirement
|
198
|
+
requirements:
|
199
|
+
- - ">="
|
200
|
+
- !ruby/object:Gem::Version
|
201
|
+
version: '0'
|
202
|
+
type: :development
|
203
|
+
prerelease: false
|
204
|
+
version_requirements: !ruby/object:Gem::Requirement
|
205
|
+
requirements:
|
206
|
+
- - ">="
|
207
|
+
- !ruby/object:Gem::Version
|
208
|
+
version: '0'
|
209
|
+
description: A faster, leaner, and simpler successor to ApiModel. Makes returning
|
210
|
+
objects from api calls a breeze.
|
211
|
+
email:
|
212
|
+
- mail@damientimewell.com
|
213
|
+
executables: []
|
214
|
+
extensions: []
|
215
|
+
extra_rdoc_files: []
|
216
|
+
files:
|
217
|
+
- MIT-LICENSE
|
218
|
+
- README.md
|
219
|
+
- Rakefile
|
220
|
+
- lib/api-blueprint.rb
|
221
|
+
- lib/api-blueprint/blueprint.rb
|
222
|
+
- lib/api-blueprint/builder.rb
|
223
|
+
- lib/api-blueprint/cache.rb
|
224
|
+
- lib/api-blueprint/collection.rb
|
225
|
+
- lib/api-blueprint/model.rb
|
226
|
+
- lib/api-blueprint/parser.rb
|
227
|
+
- lib/api-blueprint/runner.rb
|
228
|
+
- lib/api-blueprint/types.rb
|
229
|
+
- lib/api-blueprint/url.rb
|
230
|
+
- lib/api-blueprint/version.rb
|
231
|
+
homepage: https://github.com/iZettle/api-blueprint
|
232
|
+
licenses:
|
233
|
+
- MIT
|
234
|
+
metadata: {}
|
235
|
+
post_install_message:
|
236
|
+
rdoc_options: []
|
237
|
+
require_paths:
|
238
|
+
- lib
|
239
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
240
|
+
requirements:
|
241
|
+
- - ">="
|
242
|
+
- !ruby/object:Gem::Version
|
243
|
+
version: '0'
|
244
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
245
|
+
requirements:
|
246
|
+
- - ">="
|
247
|
+
- !ruby/object:Gem::Version
|
248
|
+
version: '0'
|
249
|
+
requirements: []
|
250
|
+
rubyforge_project:
|
251
|
+
rubygems_version: 2.6.14
|
252
|
+
signing_key:
|
253
|
+
specification_version: 4
|
254
|
+
summary: A faster, leaner, and simpler successor to ApiModel. Makes returning objects
|
255
|
+
from api calls a breeze.
|
256
|
+
test_files: []
|