cistern 0.11.3 → 0.12.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 +4 -4
- data/Gemfile +1 -1
- data/README.md +23 -0
- data/lib/cistern/formatter/default.rb +22 -0
- data/lib/cistern/formatter.rb +4 -0
- data/lib/cistern/model.rb +1 -5
- data/lib/cistern/request.rb +41 -0
- data/lib/cistern/service.rb +29 -4
- data/lib/cistern/string.rb +23 -0
- data/lib/cistern/version.rb +1 -1
- data/lib/cistern.rb +2 -0
- data/spec/formatter_spec.rb +56 -29
- data/spec/request_spec.rb +29 -0
- data/spec/spec_helper.rb +0 -2
- metadata +8 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 596a794e4f9c5986b6d3163405445f2712df6152
|
4
|
+
data.tar.gz: 7e49adeffc52e77885f8ab6dd4b409b0591d5bc4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9046ac54d8b3c92b9665431dd56651e4f5985c1512bba516395ac3910ae14b1806ea1a1d1cb0fb762abd1f70c010863fdaae405c258486653f9719597786565e
|
7
|
+
data.tar.gz: a46cf7e5877fb598f0b37525f7feb451f0fa8a730a8ecaba605b924d6f1a3aa96e874d5e91bcb893a7941d8e142b2ec3082a9a17603388debb238574ff1f96b7
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -58,6 +58,29 @@ All declared requests can be listed via `Cistern::Service#requests`.
|
|
58
58
|
Foo::Client.requests # => [:get_bar, :get_bars]
|
59
59
|
```
|
60
60
|
|
61
|
+
##### Forward Compatible
|
62
|
+
|
63
|
+
Ish.
|
64
|
+
|
65
|
+
```ruby
|
66
|
+
# client/requests/get_bar.rb
|
67
|
+
class Foo:Client::GetBar
|
68
|
+
|
69
|
+
service Foo::Client
|
70
|
+
|
71
|
+
def real(bar_id)
|
72
|
+
connection.request("http://example.org/bar/#{bar_id}")
|
73
|
+
end
|
74
|
+
|
75
|
+
def mock
|
76
|
+
# do some mock things
|
77
|
+
end
|
78
|
+
end
|
79
|
+
```
|
80
|
+
|
81
|
+
In this context, `connection` is reference to the `Cistern::Service`.
|
82
|
+
|
83
|
+
|
61
84
|
#### Models and Collections
|
62
85
|
|
63
86
|
Models and collections have declaration semantics similar to requests. Models and collections are enumerated via `model` and `collection` respectively.
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Cistern::Formatter::Default
|
2
|
+
class << self
|
3
|
+
def call(object)
|
4
|
+
case object
|
5
|
+
when Cistern::Collection
|
6
|
+
format_collection(object)
|
7
|
+
when Cistern::Model
|
8
|
+
format_model(object)
|
9
|
+
else
|
10
|
+
object.to_s
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def format_model(model)
|
15
|
+
"#{model.to_s} #{model.attributes.inspect}"
|
16
|
+
end
|
17
|
+
|
18
|
+
def format_collection(collection)
|
19
|
+
"#{collection.to_s} #{collection.attributes.inspect} records=[#{collection.records.map { |m| format_model(m) }.join(", ")}]"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/cistern/formatter.rb
CHANGED
data/lib/cistern/model.rb
CHANGED
@@ -5,11 +5,7 @@ class Cistern::Model
|
|
5
5
|
attr_accessor :collection, :connection
|
6
6
|
|
7
7
|
def inspect
|
8
|
-
|
9
|
-
Cistern.formatter.call(self)
|
10
|
-
else
|
11
|
-
"#<#{self.class} #{self.identity}"
|
12
|
-
end
|
8
|
+
Cistern.formatter.call(self)
|
13
9
|
end
|
14
10
|
|
15
11
|
def initialize(attributes={})
|
@@ -0,0 +1,41 @@
|
|
1
|
+
class Cistern::Request
|
2
|
+
def self.register(service, klass, method)
|
3
|
+
service.requests << [method, {class: klass, method: method, new: true}]
|
4
|
+
end
|
5
|
+
|
6
|
+
def self.service(klass, options={})
|
7
|
+
@service = klass
|
8
|
+
@service_method = options[:method] || Cistern::String.underscore(
|
9
|
+
Cistern::String.demodulize(self.name)
|
10
|
+
)
|
11
|
+
Cistern::Request.register(klass, self, @service_method)
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.service_method
|
15
|
+
@service_method
|
16
|
+
end
|
17
|
+
|
18
|
+
attr_reader :connection
|
19
|
+
|
20
|
+
alias service connection
|
21
|
+
|
22
|
+
def initialize(connection)
|
23
|
+
@connection = connection
|
24
|
+
end
|
25
|
+
|
26
|
+
def _real(*args, &block)
|
27
|
+
real(*args, &block)
|
28
|
+
end
|
29
|
+
|
30
|
+
def _mock(*args, &block)
|
31
|
+
mock(*args, &block)
|
32
|
+
end
|
33
|
+
|
34
|
+
def real(*args, &block)
|
35
|
+
raise NotImplementedError
|
36
|
+
end
|
37
|
+
|
38
|
+
def mock(*args, &block)
|
39
|
+
Cistern::Mock.not_implemented(self.class.service_method)
|
40
|
+
end
|
41
|
+
end
|
data/lib/cistern/service.rb
CHANGED
@@ -163,11 +163,34 @@ class Cistern::Service
|
|
163
163
|
|
164
164
|
# setup requests
|
165
165
|
requests.each do |request, options|
|
166
|
-
unless options[:require] == false || service::Real.method_defined?(request.to_s)
|
166
|
+
unless (options[:require] == false) || options[:new] || service::Real.method_defined?(request.to_s)
|
167
167
|
require(options[:require] || File.join(@request_path, request.to_s))
|
168
168
|
end
|
169
169
|
|
170
|
-
if
|
170
|
+
if options[:new]
|
171
|
+
klass = options.fetch(:class)
|
172
|
+
method = options.fetch(:method)
|
173
|
+
|
174
|
+
unless klass.instance_methods.include?(:mock)
|
175
|
+
klass.class_eval <<-EOS, __FILE__, __LINE__
|
176
|
+
def #{method}(*args)
|
177
|
+
Cistern::Mock.not_implemented(request)
|
178
|
+
end
|
179
|
+
EOS
|
180
|
+
end
|
181
|
+
|
182
|
+
service::Real.module_eval <<-EOS, __FILE__, __LINE__
|
183
|
+
def #{method}(*args)
|
184
|
+
#{klass}.new(self)._real(*args)
|
185
|
+
end
|
186
|
+
EOS
|
187
|
+
|
188
|
+
service::Mock.module_eval <<-EOS, __FILE__, __LINE__
|
189
|
+
def #{method}(*args)
|
190
|
+
#{klass}.new(self)._mock(*args)
|
191
|
+
end
|
192
|
+
EOS
|
193
|
+
elsif service::Mock.method_defined?(request)
|
171
194
|
mocked_requests << request
|
172
195
|
else
|
173
196
|
service::Mock.module_eval <<-EOS, __FILE__, __LINE__
|
@@ -180,11 +203,13 @@ class Cistern::Service
|
|
180
203
|
|
181
204
|
# setup collections
|
182
205
|
collections.each do |collection, options|
|
183
|
-
unless options[:require]
|
206
|
+
unless false == options[:require]
|
184
207
|
require(options[:require] || File.join(@collection_path || @model_path, collection.to_s))
|
185
208
|
end
|
186
209
|
|
187
|
-
class_name = collection.to_s.
|
210
|
+
class_name = collection.to_s.
|
211
|
+
split("/").map(&:capitalize).join("::").split("_").
|
212
|
+
map { |s| "#{s[0].upcase}#{s[1..-1]}" }.join
|
188
213
|
plural_name = options[:collection] || collection.to_s.gsub("/", "_")
|
189
214
|
|
190
215
|
self.const_get(:Collections).module_eval <<-EOS, __FILE__, __LINE__
|
@@ -0,0 +1,23 @@
|
|
1
|
+
class Cistern::String
|
2
|
+
# stolen from activesupport/lib/active_support/inflector/methods.rb, line 198
|
3
|
+
def self.demodulize(path)
|
4
|
+
path = path.to_s
|
5
|
+
if i = path.rindex('::')
|
6
|
+
path[(i+2)..-1]
|
7
|
+
else
|
8
|
+
path
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
# stolen from activesupport/lib/active_support/inflector/methods.rb, line 90
|
13
|
+
def self.underscore(camel_cased_word)
|
14
|
+
return camel_cased_word unless camel_cased_word =~ /[A-Z-]|::/
|
15
|
+
word = camel_cased_word.to_s.gsub(/::/, '/')
|
16
|
+
#word.gsub!(/(?:(?<=([A-Za-z\d]))|\b)(#{inflections.acronym_regex})(?=\b|[^a-z])/) { "#{$1 && '_'}#{$2.downcase}" }
|
17
|
+
word.gsub!(/([A-Z\d]+)([A-Z][a-z])/,'\1_\2')
|
18
|
+
word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
|
19
|
+
word.tr!("-", "_")
|
20
|
+
word.downcase!
|
21
|
+
word
|
22
|
+
end
|
23
|
+
end
|
data/lib/cistern/version.rb
CHANGED
data/lib/cistern.rb
CHANGED
data/spec/formatter_spec.rb
CHANGED
@@ -1,42 +1,75 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
class Inspector < Cistern::Model
|
4
|
+
identity :id
|
5
|
+
attribute :name
|
6
|
+
end
|
7
|
+
|
8
|
+
class Anon < Cistern::Model
|
9
|
+
attribute :chan
|
10
|
+
end
|
11
|
+
|
12
|
+
class Inspectors < Cistern::Collection
|
13
|
+
model Inspector
|
14
|
+
|
15
|
+
def all(options={})
|
16
|
+
merge_attributes(options)
|
17
|
+
self.load([{id: 1, name: "2"},{id: 3, name: "4"}])
|
7
18
|
end
|
19
|
+
end
|
8
20
|
|
9
|
-
|
21
|
+
describe Cistern::Formatter::Default do
|
22
|
+
before { Cistern.formatter = described_class }
|
10
23
|
|
11
|
-
|
24
|
+
it "formats a model" do
|
25
|
+
expect(
|
26
|
+
Inspector.new(id: 1, name: "name").inspect
|
27
|
+
).to match(
|
28
|
+
/<Inspector:0x[a-z0-9]+> {:id=>1, :name=>\"name\"}/
|
29
|
+
)
|
12
30
|
|
13
|
-
|
14
|
-
merge_attributes(options)
|
15
|
-
self.load([{id: 1, name: "2"},{id: 3, name: "4"}])
|
16
|
-
end
|
31
|
+
Anon.inspect
|
17
32
|
end
|
18
33
|
|
19
|
-
|
20
|
-
|
21
|
-
|
34
|
+
it "formats a collection" do
|
35
|
+
expect(
|
36
|
+
Inspectors.new.all.inspect
|
37
|
+
).to match(
|
38
|
+
/<Inspectors:0x[a-z0-9]+> {} records/
|
39
|
+
)
|
40
|
+
end
|
41
|
+
end
|
22
42
|
|
23
|
-
|
24
|
-
|
43
|
+
describe Cistern::Formatter::AwesomePrint do
|
44
|
+
before { Cistern.formatter = described_class }
|
25
45
|
|
26
|
-
|
27
|
-
|
46
|
+
it "formats a model" do
|
47
|
+
expect(
|
48
|
+
Inspector.new(id: 1, name: "name").inspect
|
49
|
+
).to match(
|
50
|
+
/(?x-mi:\#<Inspector:0x[0-9a-f]+>\ {\n\ \ \ \ \ \ :id\x1B\[0;37m\ =>\ \x1B\[0m\x1B\[1;34m1\x1B\[0m,\n\ \ \ \ :name\x1B\[0;37m\ =>\ \x1B\[0m\x1B\[0;33m"name"\x1B\[0m\n})/
|
51
|
+
)
|
52
|
+
end
|
53
|
+
|
54
|
+
it "formats a collection" do
|
55
|
+
expect(Inspectors.new.all.inspect).to match(/Inspectors\s+{.*}$/m) # close enough
|
56
|
+
end
|
57
|
+
end
|
28
58
|
|
29
|
-
|
59
|
+
describe Cistern::Formatter::Formatador do
|
60
|
+
before { Cistern.formatter = described_class }
|
61
|
+
|
62
|
+
it "formats a model" do
|
63
|
+
Cistern.formatter = Cistern::Formatter::Formatador
|
64
|
+
|
65
|
+
expect(Inspector.new(id: 1, name: "name").inspect).to eq(%q{ <Inspector
|
30
66
|
id=1,
|
31
67
|
name="name"
|
32
68
|
>})
|
33
|
-
end
|
34
69
|
end
|
35
70
|
|
36
|
-
|
37
|
-
|
38
|
-
Cistern.formatter = Cistern::Formatter::Formatador
|
39
|
-
expect(Inspectors.new.all.inspect).to eq(%q{ <Inspectors
|
71
|
+
it "formats a collection" do
|
72
|
+
expect(Inspectors.new.all.inspect).to eq(%q{ <Inspectors
|
40
73
|
[
|
41
74
|
<Inspector
|
42
75
|
id=1,
|
@@ -48,11 +81,5 @@ describe "#inspect" do
|
|
48
81
|
>
|
49
82
|
]
|
50
83
|
>})
|
51
|
-
end
|
52
|
-
|
53
|
-
it "should use awesome_print" do
|
54
|
-
Cistern.formatter = Cistern::Formatter::AwesomePrint
|
55
|
-
expect(Inspectors.new.all.inspect).to match(/Inspectors\s+{.*}$/m) # close enough
|
56
|
-
end
|
57
84
|
end
|
58
85
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Cistern do
|
4
|
+
class SampleService < Cistern::Service
|
5
|
+
class Real
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
class SampleService::GetSample < Cistern::Request
|
10
|
+
service SampleService
|
11
|
+
|
12
|
+
def real(*args)
|
13
|
+
args
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class ShowSamples < Cistern::Request
|
18
|
+
service SampleService, method: :list_samples
|
19
|
+
|
20
|
+
def real(*args)
|
21
|
+
{"samples" => args}
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
it "allows requests to be created in a forward compatible structure" do
|
26
|
+
expect(SampleService.new.get_sample("likewhoa")).to contain_exactly("likewhoa")
|
27
|
+
expect(SampleService.new.list_samples("likewhoa")).to eq("samples" => ["likewhoa"])
|
28
|
+
end
|
29
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -8,8 +8,6 @@ require File.expand_path('../../lib/cistern', __FILE__)
|
|
8
8
|
Bundler.require(:test)
|
9
9
|
|
10
10
|
RSpec.configure do |c|
|
11
|
-
c.treat_symbols_as_metadata_keys_with_true_values = true
|
12
|
-
|
13
11
|
if Kernel.respond_to?(:caller_locations)
|
14
12
|
require File.expand_path('../../lib/cistern/coverage', __FILE__)
|
15
13
|
else
|
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: 0.
|
4
|
+
version: 0.12.1
|
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-
|
11
|
+
date: 2015-09-01 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: API client framework extracted from Fog
|
14
14
|
email:
|
@@ -36,12 +36,15 @@ files:
|
|
36
36
|
- lib/cistern/data/redis.rb
|
37
37
|
- lib/cistern/formatter.rb
|
38
38
|
- lib/cistern/formatter/awesome_print.rb
|
39
|
+
- lib/cistern/formatter/default.rb
|
39
40
|
- lib/cistern/formatter/formatador.rb
|
40
41
|
- lib/cistern/hash.rb
|
41
42
|
- lib/cistern/mock.rb
|
42
43
|
- lib/cistern/model.rb
|
44
|
+
- lib/cistern/request.rb
|
43
45
|
- lib/cistern/service.rb
|
44
46
|
- lib/cistern/singular.rb
|
47
|
+
- lib/cistern/string.rb
|
45
48
|
- lib/cistern/timeout.rb
|
46
49
|
- lib/cistern/version.rb
|
47
50
|
- lib/cistern/wait_for.rb
|
@@ -51,6 +54,7 @@ files:
|
|
51
54
|
- spec/hash_spec.rb
|
52
55
|
- spec/mock_data_spec.rb
|
53
56
|
- spec/model_spec.rb
|
57
|
+
- spec/request_spec.rb
|
54
58
|
- spec/singular_spec.rb
|
55
59
|
- spec/spec_helper.rb
|
56
60
|
- spec/wait_for_spec.rb
|
@@ -74,7 +78,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
74
78
|
version: '0'
|
75
79
|
requirements: []
|
76
80
|
rubyforge_project:
|
77
|
-
rubygems_version: 2.
|
81
|
+
rubygems_version: 2.4.5
|
78
82
|
signing_key:
|
79
83
|
specification_version: 4
|
80
84
|
summary: API client framework
|
@@ -85,7 +89,7 @@ test_files:
|
|
85
89
|
- spec/hash_spec.rb
|
86
90
|
- spec/mock_data_spec.rb
|
87
91
|
- spec/model_spec.rb
|
92
|
+
- spec/request_spec.rb
|
88
93
|
- spec/singular_spec.rb
|
89
94
|
- spec/spec_helper.rb
|
90
95
|
- spec/wait_for_spec.rb
|
91
|
-
has_rdoc:
|