garage_client 2.1.1
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/.gitignore +8 -0
- data/.rspec +1 -0
- data/CHANGELOG.md +40 -0
- data/Gemfile +8 -0
- data/Guardfile +7 -0
- data/LICENSE.txt +22 -0
- data/README.md +196 -0
- data/Rakefile +8 -0
- data/garage_client.gemspec +36 -0
- data/gemfiles/Gemfile.faraday-0.8.x +4 -0
- data/lib/garage_client.rb +33 -0
- data/lib/garage_client/cachers/base.rb +44 -0
- data/lib/garage_client/client.rb +93 -0
- data/lib/garage_client/configuration.rb +51 -0
- data/lib/garage_client/error.rb +37 -0
- data/lib/garage_client/request.rb +38 -0
- data/lib/garage_client/request/json_encoded.rb +59 -0
- data/lib/garage_client/resource.rb +63 -0
- data/lib/garage_client/response.rb +123 -0
- data/lib/garage_client/response/cacheable.rb +27 -0
- data/lib/garage_client/response/raise_http_exception.rb +34 -0
- data/lib/garage_client/version.rb +3 -0
- data/spec/features/configuration_spec.rb +46 -0
- data/spec/fixtures/example.yaml +56 -0
- data/spec/fixtures/examples.yaml +60 -0
- data/spec/fixtures/examples_dictionary.yaml +60 -0
- data/spec/fixtures/examples_without_pagination.yaml +58 -0
- data/spec/garage_client/cacher_spec.rb +55 -0
- data/spec/garage_client/client_spec.rb +228 -0
- data/spec/garage_client/configuration_spec.rb +106 -0
- data/spec/garage_client/error_spec.rb +37 -0
- data/spec/garage_client/request/json_encoded_spec.rb +66 -0
- data/spec/garage_client/resource_spec.rb +102 -0
- data/spec/garage_client/response_spec.rb +450 -0
- data/spec/garage_client_spec.rb +48 -0
- data/spec/spec_helper.rb +56 -0
- metadata +275 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 648321b65499a513c8305e6aac962afb10bf99f6
|
4
|
+
data.tar.gz: 17c99e87555fadc63de66ac384d09a354feeb00b
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: dc3e8ea2288e52f6ec2e9d9ef1b9f92318478ea543852cf77706ca53665f20d5d63e6445d88496ad0a415733772241addb8a67ffc4529e54415883ccab20e6d4
|
7
|
+
data.tar.gz: 57c200a989fc68dcd096ced3dc853ca92eb4d03246e2d26afec236c60fd3d06332d284ed642723b8f3e396b3f6fd643f15c0e0c105ba275579009ea347d006a6
|
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
## 2.1.0
|
2
|
+
- Access token is now embedded in authorization header as a bearer token, instead of embedding in query parameter, to avoid logging and exposing access token value.
|
3
|
+
Before: access token is embedded in both query parameter (`?access_token=XXX`) and in authorization header (`Authorization: Token token="XXX"`).
|
4
|
+
After: access tok is embedded in authorization header as a bearer token (`Authorization: Bearer XXX`).
|
5
|
+
|
6
|
+
## 2.0.0
|
7
|
+
- Remove `user_agent` configuration, use `headers` option instead.
|
8
|
+
|
9
|
+
## 1.3.0
|
10
|
+
- Provide a convenient way to cache HTTP response
|
11
|
+
|
12
|
+
## 1.2.4
|
13
|
+
- Raise GarageClient::InvalidResponseType when receives invalid response (e.g. String)
|
14
|
+
|
15
|
+
## 1.2.3
|
16
|
+
- Fixed response.respond_to?(:name)
|
17
|
+
|
18
|
+
## 1.2.2
|
19
|
+
- GarageClient::Response supports Link header parsing
|
20
|
+
|
21
|
+
## 1.2.1
|
22
|
+
- Set Content-Type with multipart/form-data when multipart params are detected
|
23
|
+
|
24
|
+
## 1.2.0
|
25
|
+
- `:headers` option will overwrite the entire headers
|
26
|
+
- `:default_headers` will be deprecated. Please use `:headers`
|
27
|
+
- `Garage.version` was deprecated. Please use `Garage::VERSION`
|
28
|
+
- `Garage.configuration` was added to configure settings
|
29
|
+
|
30
|
+
## 1.1.2
|
31
|
+
- Remove needless empty module clause (7f5e13)
|
32
|
+
- Change gemspec dependency (`hashie ~> 1.2.0` to `hashie >= 1.2.0`) (632ea1)
|
33
|
+
|
34
|
+
## 1.1.1
|
35
|
+
- GarageClient::Error accepts no argument initialization
|
36
|
+
|
37
|
+
## 1.1.0
|
38
|
+
- Add ``:default_headers`` option
|
39
|
+
- Verbose exception message
|
40
|
+
- Resource#links does not raise error when _links is not existed
|
data/Gemfile
ADDED
data/Guardfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Cookpad Inc.
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,196 @@
|
|
1
|
+
# GarageClient
|
2
|
+
GarageClient is a simple Ruby library to provide a primitive client interface to the Garage application API.
|
3
|
+
|
4
|
+
## Install
|
5
|
+
Install from rake command:
|
6
|
+
|
7
|
+
```
|
8
|
+
$ bundle install
|
9
|
+
$ rake install
|
10
|
+
```
|
11
|
+
|
12
|
+
or modify Gemfile in your application and invoke `bundle install`.
|
13
|
+
|
14
|
+
```ruby
|
15
|
+
# Gemfile
|
16
|
+
gem "garage_client"
|
17
|
+
```
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
Here are quick examples.
|
21
|
+
|
22
|
+
### Client initialization
|
23
|
+
```ruby
|
24
|
+
require "garage_client"
|
25
|
+
|
26
|
+
# First, you have to create a GarageClient::Client with an access token.
|
27
|
+
# You can get `YOUR_ACCESS_TOKEN` with OAuth 2.0 flow.
|
28
|
+
client = GarageClient::Client.new(access_token: YOUR_ACCESS_TOKEN)
|
29
|
+
```
|
30
|
+
|
31
|
+
### Read from Garage application
|
32
|
+
```ruby
|
33
|
+
# GET https://garage.example.com/v1/recipes
|
34
|
+
client.get("/recipes")
|
35
|
+
|
36
|
+
# GET https://garage.example.com/v1/recipes?fields=id,name,ingredients
|
37
|
+
client.get("/recipes", fields: "id,name,ingredients")
|
38
|
+
|
39
|
+
# GET https://garage.example.com/v1/me
|
40
|
+
user = client.get("/me")
|
41
|
+
|
42
|
+
# GET https://garage.example.com/v1/users/:user_id/recipes?fields=__default__,user[id,name]
|
43
|
+
client.get("/users/#{user.id}/recipes", fields: "__default__,user[id,name]")
|
44
|
+
```
|
45
|
+
|
46
|
+
### Write to Garage application
|
47
|
+
```ruby
|
48
|
+
# POST https://garage.example.com/v1/suggestions
|
49
|
+
client.post("/suggestions", message: "suggestion message")
|
50
|
+
|
51
|
+
# POST https://garage.example.com/v1/users/:user_id/bookmark_tags with JSON {"name":"tag name"}
|
52
|
+
bookmark_tag = client.post("/users/#{user.id}/bookmark_tags", name: "tag name")
|
53
|
+
|
54
|
+
# PUT https://garage.example.com/v1/bookmark_tags/:id with JSON {"name":"new tag name"}
|
55
|
+
client.put("/bookmark_tags/#{bookmark_tag.id}", name: "new tag name")
|
56
|
+
|
57
|
+
# DELETE https://garage.example.com/v1/bookmark_tags/:id
|
58
|
+
client.delete("/bookmark_tags/#{bookmark_tag.id}")
|
59
|
+
```
|
60
|
+
|
61
|
+
### Response
|
62
|
+
```ruby
|
63
|
+
# `.get` method returns a GarageClient::Response of a resource.
|
64
|
+
user = client.get("/me")
|
65
|
+
user.id
|
66
|
+
user.url
|
67
|
+
user.name
|
68
|
+
|
69
|
+
# `.get` method also returns a GarageClient::Response of an array of resources.
|
70
|
+
# In this case, the response object can respond to `.total_count` method.
|
71
|
+
recipes = client.get("/recipes")
|
72
|
+
recipes.total_count
|
73
|
+
recipes[0].id
|
74
|
+
recipes[0].name
|
75
|
+
|
76
|
+
# While Garage application API returns all default properties, some additional properties are not included in them.
|
77
|
+
# You can specify the returned properties by `?fields=...` URI query parameters.
|
78
|
+
recipes = client.get("/recipes", fields: "__default__,user")
|
79
|
+
recipes[0].id
|
80
|
+
recipes[0].name
|
81
|
+
recipes[0].user.id
|
82
|
+
recipes[0].user.url
|
83
|
+
recipes[0].user.name
|
84
|
+
|
85
|
+
# `.post` method also returns a GarageClient::Response of the newly created resource.
|
86
|
+
suggestion = client.post("/suggestions", message: "suggestion message")
|
87
|
+
suggestion.message
|
88
|
+
```
|
89
|
+
|
90
|
+
## Configuration
|
91
|
+
There are the following options:
|
92
|
+
|
93
|
+
- `adapter` - faraday adapter for http client (default: `:net_http`)
|
94
|
+
- `cacher` - take a cacher class in which caching logic is defined (default: nil)
|
95
|
+
- `headers` - default http headers (default: `{ "Accept" => "application/json", "User-Agent" => "garage_client #{VERSION}" }`)
|
96
|
+
- `endpoint` - Garage application API endpoint (default: nil)
|
97
|
+
- `path_prefix` - API path prefix (default: `'/v1'`)
|
98
|
+
- `verbose` - Enable verbose http log (default: `false`)
|
99
|
+
|
100
|
+
You can configure the global settings:
|
101
|
+
|
102
|
+
```ruby
|
103
|
+
GarageClient.configure do |c|
|
104
|
+
c.endpoint = "http://localhost:3000"
|
105
|
+
c.verbose = true
|
106
|
+
end
|
107
|
+
```
|
108
|
+
|
109
|
+
or each GarageClient::Client settings:
|
110
|
+
|
111
|
+
```ruby
|
112
|
+
client = GarageClient::Client.new(
|
113
|
+
adapter: :test,
|
114
|
+
headers: { "Host" => "garage.example.com" },
|
115
|
+
endpoint: "http://localhost:3000",
|
116
|
+
path_prefix: "/v2",
|
117
|
+
verbose: true,
|
118
|
+
)
|
119
|
+
```
|
120
|
+
|
121
|
+
## Exceptions
|
122
|
+
GarageClient raises one of the following exceptions upon an error.
|
123
|
+
Make sure to always look out for these in your code.
|
124
|
+
|
125
|
+
```ruby
|
126
|
+
GarageClient::Unauthorized
|
127
|
+
GarageClient::Forbidden
|
128
|
+
GarageClient::NotFound
|
129
|
+
GarageClient::NotAcceptable
|
130
|
+
GarageClient::Conflict
|
131
|
+
GarageClient::UnsupportedMediaType
|
132
|
+
GarageClient::UnprocessableEntity
|
133
|
+
GarageClient::InternalServerError
|
134
|
+
GarageClient::ServiceUnavailable
|
135
|
+
```
|
136
|
+
|
137
|
+
## Utility
|
138
|
+
`.properties` returns a list of properties of the resource.
|
139
|
+
|
140
|
+
```ruby
|
141
|
+
user = client.get("/me")
|
142
|
+
user.properties #=> [:id, :url, :name, :_links]
|
143
|
+
```
|
144
|
+
|
145
|
+
`.links` returns a list of link names related to the resource.
|
146
|
+
|
147
|
+
```ruby
|
148
|
+
user = client.get("/me")
|
149
|
+
user.properties #=> [:self, :bookmarks, :recipes, ...]
|
150
|
+
user.links.recipes #=> "https://garage.example.com/v1/users/:user_id/recipes"
|
151
|
+
```
|
152
|
+
|
153
|
+
## Caching
|
154
|
+
Define a cacher class with your custom caching logic to let it cache response, inheriting GarageClient::Cachers::Base.
|
155
|
+
It must override `read_from_cache?`, `written_to_cache?`, `key`, and `store` to compose your caching logic.
|
156
|
+
|
157
|
+
```ruby
|
158
|
+
class MyCacher < GarageClient::Cachers::Base
|
159
|
+
private
|
160
|
+
|
161
|
+
def read_from_cache?
|
162
|
+
has_get_method? && has_cached_path?
|
163
|
+
end
|
164
|
+
|
165
|
+
def written_to_cache?
|
166
|
+
read_from_cache?
|
167
|
+
end
|
168
|
+
|
169
|
+
def key
|
170
|
+
@env[:url].to_s
|
171
|
+
end
|
172
|
+
|
173
|
+
def store
|
174
|
+
Rails.cache
|
175
|
+
end
|
176
|
+
|
177
|
+
def options
|
178
|
+
{ expires_in: 5.minutes }
|
179
|
+
end
|
180
|
+
|
181
|
+
def has_get_method?
|
182
|
+
@env[:method] == :get
|
183
|
+
end
|
184
|
+
|
185
|
+
def has_cached_path?
|
186
|
+
case @env[:url].path
|
187
|
+
when %r<^/v1/searches>
|
188
|
+
true
|
189
|
+
when %r<^/v1/recipes/\d+>
|
190
|
+
true
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
GarageClient::Client.new(cacher: MyCacher)
|
196
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.unshift File.expand_path("../lib", __FILE__)
|
3
|
+
require 'garage_client/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.version = GarageClient::VERSION
|
7
|
+
s.name = "garage_client"
|
8
|
+
s.homepage = "https://github.com/cookpad/garage_client"
|
9
|
+
s.summary = "Ruby client library for the Garage API"
|
10
|
+
s.description = s.summary
|
11
|
+
|
12
|
+
s.files = `git ls-files`.split($\)
|
13
|
+
s.executables = s.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
14
|
+
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
15
|
+
s.require_paths = ['lib']
|
16
|
+
s.authors = ['Cookpad Inc.']
|
17
|
+
s.email = ['kaihatsu@cookpad.com']
|
18
|
+
|
19
|
+
s.add_dependency 'activesupport', '> 3.2.0'
|
20
|
+
s.add_dependency 'faraday', '>= 0.8.0'
|
21
|
+
s.add_dependency 'faraday_middleware'
|
22
|
+
s.add_dependency 'hashie', '>= 1.2.0'
|
23
|
+
s.add_dependency 'link_header'
|
24
|
+
s.add_dependency 'mime-types', '~> 1.16'
|
25
|
+
|
26
|
+
s.add_dependency 'system_timer' if RUBY_VERSION < '1.9'
|
27
|
+
|
28
|
+
s.add_development_dependency "rake", ">= 0.9.2"
|
29
|
+
s.add_development_dependency "rspec"
|
30
|
+
s.add_development_dependency "json"
|
31
|
+
s.add_development_dependency "guard-rspec"
|
32
|
+
s.add_development_dependency "webmock"
|
33
|
+
s.add_development_dependency "pry"
|
34
|
+
# Until bug fixed: https://github.com/colszowka/simplecov/issues/281
|
35
|
+
s.add_development_dependency "simplecov", "~> 0.7.1"
|
36
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'active_support/all'
|
2
|
+
require 'faraday'
|
3
|
+
require 'faraday_middleware'
|
4
|
+
|
5
|
+
require 'garage_client/version'
|
6
|
+
require 'garage_client/cachers/base'
|
7
|
+
require 'garage_client/configuration'
|
8
|
+
require 'garage_client/error'
|
9
|
+
require 'garage_client/request'
|
10
|
+
require 'garage_client/request/json_encoded'
|
11
|
+
require 'garage_client/response'
|
12
|
+
require 'garage_client/response/cacheable'
|
13
|
+
require 'garage_client/response/raise_http_exception'
|
14
|
+
require 'garage_client/resource'
|
15
|
+
require 'garage_client/client'
|
16
|
+
|
17
|
+
module GarageClient
|
18
|
+
class << self
|
19
|
+
GarageClient::Configuration.keys.each do |key|
|
20
|
+
delegate key, "#{key}=", to: :configuration
|
21
|
+
end
|
22
|
+
|
23
|
+
delegate 'default_headers', 'default_headers=', to: :configuration
|
24
|
+
|
25
|
+
def configuration
|
26
|
+
@configuration ||= GarageClient::Configuration.new
|
27
|
+
end
|
28
|
+
|
29
|
+
def configure(&block)
|
30
|
+
configuration.instance_eval(&block)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# Inherit this abstract class and pass it to garage_client client to cache its responses.
|
2
|
+
module GarageClient
|
3
|
+
module Cachers
|
4
|
+
class Base
|
5
|
+
def initialize(env)
|
6
|
+
@env = env
|
7
|
+
end
|
8
|
+
|
9
|
+
def call
|
10
|
+
response = read_from_cache? && store.read(key, options) || yield
|
11
|
+
store.write(key, response, options) if written_to_cache?
|
12
|
+
response
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
# Return boolean to tell if we need to cache the response or not.
|
18
|
+
def allowed_to_read_cache?
|
19
|
+
raise NotImplementedError, "You must implement #{self.class}##{__method__}"
|
20
|
+
end
|
21
|
+
|
22
|
+
# Return boolean to tell if we can try to check cache or not.
|
23
|
+
def allowed_to_write_cache?
|
24
|
+
raise NotImplementedError, "You must implement #{self.class}##{__method__}"
|
25
|
+
end
|
26
|
+
|
27
|
+
# Return string to cache key to store a given HTTP response.
|
28
|
+
def key
|
29
|
+
raise NotImplementedError, "You must implement #{self.class}##{__method__}"
|
30
|
+
end
|
31
|
+
|
32
|
+
# Return store-object to get or write response (e.g. Rails.cache).
|
33
|
+
# This store-object must respond to `fetch(key, options)` method signature.
|
34
|
+
def store
|
35
|
+
raise NotImplementedError, "You must implement #{self.class}##{__method__}"
|
36
|
+
end
|
37
|
+
|
38
|
+
# Return hash table to be used as store's options.
|
39
|
+
def options
|
40
|
+
{}
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
module GarageClient
|
2
|
+
class Client
|
3
|
+
include GarageClient::Request
|
4
|
+
|
5
|
+
def self.property(key)
|
6
|
+
define_method(key) do
|
7
|
+
options.fetch(key, GarageClient.configuration.send(key))
|
8
|
+
end
|
9
|
+
|
10
|
+
define_method("#{key}=") do |value|
|
11
|
+
options[key] = value
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
attr_reader :options
|
16
|
+
|
17
|
+
property :adapter
|
18
|
+
property :cacher
|
19
|
+
property :endpoint
|
20
|
+
property :path_prefix
|
21
|
+
property :verbose
|
22
|
+
|
23
|
+
def initialize(options = {})
|
24
|
+
require_necessaries(options)
|
25
|
+
@options = options
|
26
|
+
end
|
27
|
+
|
28
|
+
def headers
|
29
|
+
@headers ||= GarageClient.configuration.headers.merge(given_headers.stringify_keys)
|
30
|
+
end
|
31
|
+
alias :default_headers :headers
|
32
|
+
|
33
|
+
def headers=(value)
|
34
|
+
@headers = value
|
35
|
+
end
|
36
|
+
alias :default_headers= :headers=
|
37
|
+
|
38
|
+
def access_token
|
39
|
+
options[:access_token]
|
40
|
+
end
|
41
|
+
|
42
|
+
def access_token=(value)
|
43
|
+
options[:access_token] = value
|
44
|
+
end
|
45
|
+
|
46
|
+
def me(params = {}, options = {})
|
47
|
+
get('/me', params, options)
|
48
|
+
end
|
49
|
+
|
50
|
+
def conn
|
51
|
+
@conn ||= connection
|
52
|
+
end
|
53
|
+
|
54
|
+
def apply_auth_middleware(faraday_builder)
|
55
|
+
faraday_builder.authorization :Bearer, access_token if access_token
|
56
|
+
end
|
57
|
+
|
58
|
+
def connection
|
59
|
+
Faraday.new(headers: headers, url: endpoint) do |builder|
|
60
|
+
# Response Middlewares
|
61
|
+
builder.use Faraday::Response::Logger if verbose
|
62
|
+
builder.use FaradayMiddleware::Mashify
|
63
|
+
builder.use Faraday::Response::ParseJson, :content_type => /\bjson$/
|
64
|
+
builder.use GarageClient::Response::Cacheable, cacher: cacher if cacher
|
65
|
+
builder.use GarageClient::Response::RaiseHttpException
|
66
|
+
|
67
|
+
# Request Middlewares
|
68
|
+
builder.use Faraday::Request::Multipart
|
69
|
+
builder.use GarageClient::Request::JsonEncoded
|
70
|
+
|
71
|
+
# Low-level Middlewares
|
72
|
+
apply_auth_middleware builder
|
73
|
+
builder.adapter(*adapter)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
def given_headers
|
80
|
+
options[:headers] || options[:default_headers] || {}
|
81
|
+
end
|
82
|
+
|
83
|
+
def require_necessaries(options)
|
84
|
+
if !options[:endpoint] && !default_options.endpoint
|
85
|
+
raise "Missing endpoint configuration"
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def default_options
|
90
|
+
GarageClient.configuration
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|