cistern 2.0.5 → 2.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 +4 -4
- data/README.md +7 -3
- data/lib/cistern/client.rb +192 -0
- data/lib/cistern/service.rb +6 -185
- data/lib/cistern/version.rb +1 -1
- data/lib/cistern.rb +16 -1
- data/spec/model_spec.rb +4 -2
- data/spec/spec_helper.rb +2 -0
- data/spec/support/service.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5db3cc1e5afb1123c9118dffecb14ff09e856775
|
4
|
+
data.tar.gz: baecd5ac5ed70c005256852169d83cf378878f13
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 19a35e7fdc627b77faeaad765971c1bcb71674918209545b7d33adfa377be0dbb703ab3c38453c09074eea278064b824e86dc33cf8866cccf39c55c8de55ec5c
|
7
|
+
data.tar.gz: 14993c84e82145d7d81f357a98bd50fcb8a9f0f99df0210529e2d9a84164fe005839a1ec4d8f1043240d522ac2cc4d7c790a9f1ef22f756d66be92d71c8be059
|
data/README.md
CHANGED
@@ -16,7 +16,9 @@ This represents the remote service that you are wrapping. If the service name is
|
|
16
16
|
Service initialization parameters are enumerated by `requires` and `recognizes`. Parameters defined using `recognizes` are optional.
|
17
17
|
|
18
18
|
```ruby
|
19
|
-
class Foo::Client
|
19
|
+
class Foo::Client
|
20
|
+
include Cistern::Client
|
21
|
+
|
20
22
|
requires :hmac_id, :hmac_secret
|
21
23
|
recognizes :url
|
22
24
|
end
|
@@ -85,7 +87,7 @@ Foo::Client.new.respond_to?(:get_bars) # false
|
|
85
87
|
Foo::Client.new.get_all_the_bars # "all the bars"
|
86
88
|
```
|
87
89
|
|
88
|
-
All declared requests can be listed via `Cistern::
|
90
|
+
All declared requests can be listed via `Cistern::Client#requests`.
|
89
91
|
|
90
92
|
```ruby
|
91
93
|
Foo::Client.requests # => [Foo::Client::GetBars, Foo::Client::GetBar]
|
@@ -233,7 +235,9 @@ client.data.object_id # 70199868378300
|
|
233
235
|
You can make the service bypass Cistern's mock data structures by simply creating a `self.data` function in your service `Mock` declaration.
|
234
236
|
|
235
237
|
```ruby
|
236
|
-
class Foo::Client
|
238
|
+
class Foo::Client
|
239
|
+
include Cistern::Client
|
240
|
+
|
237
241
|
class Mock
|
238
242
|
def self.data
|
239
243
|
@data ||= {}
|
@@ -0,0 +1,192 @@
|
|
1
|
+
module Cistern::Client
|
2
|
+
|
3
|
+
module Collections
|
4
|
+
def collections
|
5
|
+
service.collections
|
6
|
+
end
|
7
|
+
|
8
|
+
def requests
|
9
|
+
service.requests
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.included(klass)
|
14
|
+
klass.class_eval <<-EOS, __FILE__, __LINE__
|
15
|
+
module Collections
|
16
|
+
include Cistern::Client::Collections
|
17
|
+
|
18
|
+
def service
|
19
|
+
#{klass.name}
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.service
|
24
|
+
#{klass.name}
|
25
|
+
end
|
26
|
+
|
27
|
+
class Real
|
28
|
+
def initialize(options={})
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class Mock
|
33
|
+
def initialize(options={})
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class Model
|
38
|
+
include Cistern::Model
|
39
|
+
|
40
|
+
def self.inherited(klass)
|
41
|
+
service.models << klass
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.service
|
45
|
+
#{klass.name}
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
class Collection
|
50
|
+
include Cistern::Collection
|
51
|
+
|
52
|
+
def self.inherited(klass)
|
53
|
+
klass.send(:extend, Cistern::Attributes::ClassMethods)
|
54
|
+
klass.send(:extend, Cistern::Collection::ClassMethods)
|
55
|
+
klass.send(:include, Cistern::Attributes::InstanceMethods)
|
56
|
+
|
57
|
+
service.collections << klass
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.service
|
61
|
+
#{klass.name}
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
class Request
|
66
|
+
include Cistern::Request
|
67
|
+
|
68
|
+
def self.inherited(klass)
|
69
|
+
klass.extend(Cistern::Request::ClassMethods)
|
70
|
+
|
71
|
+
service.requests << klass
|
72
|
+
end
|
73
|
+
|
74
|
+
def self.service
|
75
|
+
#{klass.name}
|
76
|
+
end
|
77
|
+
|
78
|
+
def _mock(*args)
|
79
|
+
mock(*args)
|
80
|
+
end
|
81
|
+
|
82
|
+
def _real(*args)
|
83
|
+
real(*args)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
EOS
|
87
|
+
|
88
|
+
klass.send(:extend, Cistern::Client::ClassMethods)
|
89
|
+
klass.send(:const_set, :Timeout, Class.new(Cistern::Error))
|
90
|
+
|
91
|
+
klass::Mock.send(:include, klass::Collections)
|
92
|
+
klass::Mock.send(:extend, Cistern::WaitFor)
|
93
|
+
klass::Mock.timeout_error = klass::Timeout
|
94
|
+
|
95
|
+
klass::Mock.send(:extend, Cistern::Data)
|
96
|
+
|
97
|
+
klass::Real.send(:include, klass::Collections)
|
98
|
+
klass::Real.send(:extend, Cistern::WaitFor)
|
99
|
+
klass::Real.timeout_error = klass::Timeout
|
100
|
+
|
101
|
+
super
|
102
|
+
end
|
103
|
+
|
104
|
+
module ClassMethods
|
105
|
+
|
106
|
+
def mock!; @mocking = true; end
|
107
|
+
def mocking?; @mocking; end
|
108
|
+
def unmock!; @mocking = false; end
|
109
|
+
|
110
|
+
def collections
|
111
|
+
@collections ||= []
|
112
|
+
end
|
113
|
+
|
114
|
+
def models
|
115
|
+
@_models ||= []
|
116
|
+
end
|
117
|
+
|
118
|
+
def recognized_arguments
|
119
|
+
@_recognized_arguments ||= []
|
120
|
+
end
|
121
|
+
|
122
|
+
def required_arguments
|
123
|
+
@_required_arguments ||= []
|
124
|
+
end
|
125
|
+
|
126
|
+
def requests
|
127
|
+
@_requests ||= []
|
128
|
+
end
|
129
|
+
|
130
|
+
def requires(*args)
|
131
|
+
self.required_arguments.concat(args)
|
132
|
+
end
|
133
|
+
|
134
|
+
def recognizes(*args)
|
135
|
+
self.recognized_arguments.concat(args)
|
136
|
+
end
|
137
|
+
|
138
|
+
def validate_options(options={})
|
139
|
+
required_options = Cistern::Hash.slice(options, *required_arguments)
|
140
|
+
|
141
|
+
missing_required_options = required_arguments - required_options.keys
|
142
|
+
|
143
|
+
unless missing_required_options.empty?
|
144
|
+
raise "Missing required options: #{missing_required_options.inspect}"
|
145
|
+
end
|
146
|
+
|
147
|
+
unrecognized_options = options.keys - (required_arguments + recognized_arguments)
|
148
|
+
|
149
|
+
unless unrecognized_options.empty?
|
150
|
+
raise "Unrecognized options: #{unrecognized_options.inspect}"
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def setup
|
155
|
+
return true if @_setup
|
156
|
+
|
157
|
+
requests.each do |klass|
|
158
|
+
name = klass.service_method ||
|
159
|
+
Cistern::String.camelize(Cistern::String.demodulize(klass.name))
|
160
|
+
|
161
|
+
Cistern::Request.service_request(self, klass, name)
|
162
|
+
end
|
163
|
+
|
164
|
+
collections.each do |klass|
|
165
|
+
name = klass.service_method ||
|
166
|
+
Cistern::String.underscore(klass.name.gsub("#{self.name}::", "").gsub("::", ""))
|
167
|
+
|
168
|
+
Cistern::Collection.service_collection(self, klass, name)
|
169
|
+
end
|
170
|
+
|
171
|
+
models.each do |klass|
|
172
|
+
name = klass.service_method ||
|
173
|
+
Cistern::String.underscore(klass.name.gsub("#{self.name}::", "").gsub("::", ""))
|
174
|
+
|
175
|
+
Cistern::Model.service_model(self, klass, name)
|
176
|
+
end
|
177
|
+
|
178
|
+
@_setup = true
|
179
|
+
end
|
180
|
+
|
181
|
+
def new(options={})
|
182
|
+
setup
|
183
|
+
validate_options(options)
|
184
|
+
|
185
|
+
self.const_get(self.mocking? ? :Mock : :Real).new(options)
|
186
|
+
end
|
187
|
+
|
188
|
+
def reset!
|
189
|
+
self.const_get(:Mock).reset!
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
data/lib/cistern/service.rb
CHANGED
@@ -1,188 +1,9 @@
|
|
1
1
|
class Cistern::Service
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
def collections
|
9
|
-
service.collections
|
10
|
-
end
|
11
|
-
|
12
|
-
def requests
|
13
|
-
service.requests
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
class << self
|
18
|
-
def inherited(klass)
|
19
|
-
klass.class_eval <<-EOS, __FILE__, __LINE__
|
20
|
-
module Collections
|
21
|
-
include Cistern::Service::Collections
|
22
|
-
|
23
|
-
def service
|
24
|
-
#{klass.name}
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
def self.service
|
29
|
-
#{klass.name}
|
30
|
-
end
|
31
|
-
|
32
|
-
class Real
|
33
|
-
def initialize(options={})
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
class Mock
|
38
|
-
def initialize(options={})
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
class Model
|
43
|
-
include Cistern::Model
|
44
|
-
|
45
|
-
def self.inherited(klass)
|
46
|
-
service.models << klass
|
47
|
-
end
|
48
|
-
|
49
|
-
def self.service
|
50
|
-
#{klass.name}
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
class Collection
|
55
|
-
include Cistern::Collection
|
56
|
-
|
57
|
-
def self.inherited(klass)
|
58
|
-
klass.send(:extend, Cistern::Attributes::ClassMethods)
|
59
|
-
klass.send(:extend, Cistern::Collection::ClassMethods)
|
60
|
-
klass.send(:include, Cistern::Attributes::InstanceMethods)
|
61
|
-
|
62
|
-
service.collections << klass
|
63
|
-
end
|
64
|
-
|
65
|
-
def self.service
|
66
|
-
#{klass.name}
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
class Request
|
71
|
-
include Cistern::Request
|
72
|
-
|
73
|
-
def self.inherited(klass)
|
74
|
-
klass.extend(Cistern::Request::ClassMethods)
|
75
|
-
|
76
|
-
service.requests << klass
|
77
|
-
end
|
78
|
-
|
79
|
-
def self.service
|
80
|
-
#{klass.name}
|
81
|
-
end
|
82
|
-
|
83
|
-
def _mock(*args)
|
84
|
-
mock(*args)
|
85
|
-
end
|
86
|
-
|
87
|
-
def _real(*args)
|
88
|
-
real(*args)
|
89
|
-
end
|
90
|
-
end
|
91
|
-
EOS
|
92
|
-
|
93
|
-
klass.send(:const_set, :Timeout, Class.new(Cistern::Error))
|
94
|
-
|
95
|
-
klass::Mock.send(:include, klass::Collections)
|
96
|
-
klass::Mock.send(:extend, Cistern::WaitFor)
|
97
|
-
klass::Mock.timeout_error = klass::Timeout
|
98
|
-
|
99
|
-
klass::Mock.send(:extend, Cistern::Data)
|
100
|
-
|
101
|
-
klass::Real.send(:include, klass::Collections)
|
102
|
-
klass::Real.send(:extend, Cistern::WaitFor)
|
103
|
-
klass::Real.timeout_error = klass::Timeout
|
104
|
-
end
|
105
|
-
|
106
|
-
def collections
|
107
|
-
@collections ||= []
|
108
|
-
end
|
109
|
-
|
110
|
-
def models
|
111
|
-
@_models ||= []
|
112
|
-
end
|
113
|
-
|
114
|
-
def recognized_arguments
|
115
|
-
@_recognized_arguments ||= []
|
116
|
-
end
|
117
|
-
|
118
|
-
def required_arguments
|
119
|
-
@_required_arguments ||= []
|
120
|
-
end
|
121
|
-
|
122
|
-
def requests
|
123
|
-
@_requests ||= []
|
124
|
-
end
|
125
|
-
|
126
|
-
def requires(*args)
|
127
|
-
self.required_arguments.concat(args)
|
128
|
-
end
|
129
|
-
|
130
|
-
def recognizes(*args)
|
131
|
-
self.recognized_arguments.concat(args)
|
132
|
-
end
|
133
|
-
|
134
|
-
def validate_options(options={})
|
135
|
-
required_options = Cistern::Hash.slice(options, *required_arguments)
|
136
|
-
|
137
|
-
missing_required_options = required_arguments - required_options.keys
|
138
|
-
|
139
|
-
unless missing_required_options.empty?
|
140
|
-
raise "Missing required options: #{missing_required_options.inspect}"
|
141
|
-
end
|
142
|
-
|
143
|
-
unrecognized_options = options.keys - (required_arguments + recognized_arguments)
|
144
|
-
|
145
|
-
unless unrecognized_options.empty?
|
146
|
-
raise "Unrecognized options: #{unrecognized_options.inspect}"
|
147
|
-
end
|
148
|
-
end
|
149
|
-
|
150
|
-
def setup
|
151
|
-
return true if @_setup
|
152
|
-
|
153
|
-
requests.each do |klass|
|
154
|
-
name = klass.service_method ||
|
155
|
-
Cistern::String.camelize(Cistern::String.demodulize(klass.name))
|
156
|
-
|
157
|
-
Cistern::Request.service_request(self, klass, name)
|
158
|
-
end
|
159
|
-
|
160
|
-
collections.each do |klass|
|
161
|
-
name = klass.service_method ||
|
162
|
-
Cistern::String.underscore(klass.name.gsub("#{self.name}::", "").gsub("::", ""))
|
163
|
-
|
164
|
-
Cistern::Collection.service_collection(self, klass, name)
|
165
|
-
end
|
166
|
-
|
167
|
-
models.each do |klass|
|
168
|
-
name = klass.service_method ||
|
169
|
-
Cistern::String.underscore(klass.name.gsub("#{self.name}::", "").gsub("::", ""))
|
170
|
-
|
171
|
-
Cistern::Model.service_model(self, klass, name)
|
172
|
-
end
|
173
|
-
|
174
|
-
@_setup = true
|
175
|
-
end
|
176
|
-
|
177
|
-
def new(options={})
|
178
|
-
setup
|
179
|
-
validate_options(options)
|
180
|
-
|
181
|
-
self.const_get(self.mocking? ? :Mock : :Real).new(options)
|
182
|
-
end
|
183
|
-
|
184
|
-
def reset!
|
185
|
-
self.const_get(:Mock).reset!
|
186
|
-
end
|
2
|
+
def self.inherited(klass)
|
3
|
+
Cistern.deprecation(
|
4
|
+
%q{subclassing Cistern::Service is deprecated. Please use `include Cistern::Client`},
|
5
|
+
caller[0],
|
6
|
+
)
|
7
|
+
klass.send(:include, Cistern::Client)
|
187
8
|
end
|
188
9
|
end
|
data/lib/cistern/version.rb
CHANGED
data/lib/cistern.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'cistern/version'
|
2
2
|
|
3
|
+
# stdlib
|
3
4
|
require 'time'
|
4
|
-
require 'set'
|
5
5
|
|
6
6
|
module Cistern
|
7
7
|
|
@@ -16,6 +16,7 @@ module Cistern
|
|
16
16
|
require 'cistern/collection'
|
17
17
|
require 'cistern/model'
|
18
18
|
require 'cistern/service'
|
19
|
+
require 'cistern/client'
|
19
20
|
require 'cistern/singular'
|
20
21
|
require 'cistern/request'
|
21
22
|
require 'cistern/data'
|
@@ -31,6 +32,20 @@ module Cistern
|
|
31
32
|
def self.formatter
|
32
33
|
@formatter ||= Cistern::Formatter.default
|
33
34
|
end
|
35
|
+
|
36
|
+
def self.deprecation_warnings?
|
37
|
+
@deprecation_warnings.nil? ? true : !!@deprecation_warnings
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.deprecation_warnings=(status)
|
41
|
+
@deprecation_warnings = status
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.deprecation(message, source=caller[1])
|
45
|
+
if deprecation_warnings?
|
46
|
+
STDERR.puts("#{message}. (#{source})")
|
47
|
+
end
|
48
|
+
end
|
34
49
|
end
|
35
50
|
|
36
51
|
Cistern.timeout = 180 # 3 minutes
|
data/spec/model_spec.rb
CHANGED
@@ -38,7 +38,8 @@ describe "Cistern::Model" do
|
|
38
38
|
end
|
39
39
|
|
40
40
|
it "should set singular resource service method" do
|
41
|
-
class ModelService
|
41
|
+
class ModelService
|
42
|
+
include Cistern::Client
|
42
43
|
end
|
43
44
|
|
44
45
|
class ModelService::Jimbob < ModelService::Model
|
@@ -49,7 +50,8 @@ describe "Cistern::Model" do
|
|
49
50
|
end
|
50
51
|
|
51
52
|
it "should set specific singular resource service method" do
|
52
|
-
class SpecificModelService
|
53
|
+
class SpecificModelService
|
54
|
+
include Cistern::Client
|
53
55
|
end
|
54
56
|
|
55
57
|
class SpecificModelService::Jimbob < SpecificModelService::Model
|
data/spec/spec_helper.rb
CHANGED
data/spec/support/service.rb
CHANGED
@@ -1 +1 @@
|
|
1
|
-
class Sample
|
1
|
+
class Sample; include Cistern::Client; end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cistern
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0
|
4
|
+
version: 2.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Josh Lane
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-09-
|
11
|
+
date: 2015-09-29 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: API client framework extracted from Fog
|
14
14
|
email:
|
@@ -30,6 +30,7 @@ files:
|
|
30
30
|
- cistern.gemspec
|
31
31
|
- lib/cistern.rb
|
32
32
|
- lib/cistern/attributes.rb
|
33
|
+
- lib/cistern/client.rb
|
33
34
|
- lib/cistern/collection.rb
|
34
35
|
- lib/cistern/coverage.rb
|
35
36
|
- lib/cistern/data.rb
|