cistern 2.1.0 → 2.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5db3cc1e5afb1123c9118dffecb14ff09e856775
4
- data.tar.gz: baecd5ac5ed70c005256852169d83cf378878f13
3
+ metadata.gz: 32675f1c34663bf47fbea19c1f56e009884b8851
4
+ data.tar.gz: bd418e9510d7dfde5bc563a0e8a3471b174c6a2a
5
5
  SHA512:
6
- metadata.gz: 19a35e7fdc627b77faeaad765971c1bcb71674918209545b7d33adfa377be0dbb703ab3c38453c09074eea278064b824e86dc33cf8866cccf39c55c8de55ec5c
7
- data.tar.gz: 14993c84e82145d7d81f357a98bd50fcb8a9f0f99df0210529e2d9a84164fe005839a1ec4d8f1043240d522ac2cc4d7c790a9f1ef22f756d66be92d71c8be059
6
+ metadata.gz: 4f5044d67c9c3195a7ea0ec3f50186c4746aba1dec07cb16e582dc92d5b35219e913b9eeaef651ea75f71e6fc143603216339179627a516975741ccbf0c26014
7
+ data.tar.gz: 9db86cbe754c36b2c3f07e33b1b44c01d1c10dc97a746a61dd59cc1f616dd7574477b09c3ef0af24a5d1c7c025ff8a6d7162591c81ab4679746b2a1223bef0c7
data/Gemfile CHANGED
@@ -8,7 +8,7 @@ group :test do
8
8
  gem "guard-bundler", "~> 2.0", require: false
9
9
  gem "pry-nav"
10
10
  gem "rake"
11
- gem "rspec", "~> 2.99"
11
+ gem "rspec", "~> 3.3"
12
12
  gem "redis-namespace", "~> 1.4", "< 1.5"
13
13
  gem "codeclimate-test-reporter", require: false
14
14
  end
data/README.md CHANGED
@@ -9,6 +9,61 @@ Cistern helps you consistently build your API clients and faciliates building mo
9
9
 
10
10
  ## Usage
11
11
 
12
+ ### Custom Architecture
13
+
14
+ By default a service's `Request`, `Collection`, and `Model` are all classes. In Cistern ~> 3.0, the default will be modules.
15
+
16
+ You can modify your client's architecture to be forwards compatible by using `Cistern::Client.with`
17
+
18
+ ```ruby
19
+ class Foo::Client
20
+ include Cistern::Client.with(interface: :module)
21
+ end
22
+ ```
23
+
24
+ Now request classes would look like:
25
+
26
+ ```ruby
27
+ class Foo::GetBar
28
+ include Foo::Request
29
+
30
+ def real
31
+ "bar"
32
+ end
33
+ end
34
+ ```
35
+
36
+ Other options include `:collection`, `:request`, and `:model`. This options define the name of module or class interface for the service component.
37
+
38
+ If `Request` is to reserved for a model, then the `Request` component name can be remapped to `Prayer`
39
+
40
+ For example:
41
+
42
+ ```ruby
43
+ class Foo::Client
44
+ include Cistern::Client.with(request: "Prayer")
45
+ end
46
+ ```
47
+
48
+ allows a model named `Request` to exist
49
+
50
+ ```ruby
51
+ class Foo::Request < Foo::Model
52
+ identity :jovi
53
+ end
54
+ ```
55
+
56
+ while living on a `Prayer`
57
+
58
+ ```ruby
59
+ class Foo::GetBar < Foo::Prayer
60
+ def real
61
+ service.request.get("/wing")
62
+ end
63
+ end
64
+ ```
65
+
66
+
12
67
  ### Service
13
68
 
14
69
  This represents the remote service that you are wrapping. If the service name is `foo` then a good name is `Foo::Client`.
@@ -10,79 +10,120 @@ module Cistern::Client
10
10
  end
11
11
  end
12
12
 
13
+ # custom include
14
+ def self.with(options={})
15
+ client_module = Module.new
16
+
17
+ custom_include = <<-EOS
18
+ def self.included(klass)
19
+ Cistern::Client.setup(klass, #{options.inspect})
20
+
21
+ super
22
+ end
23
+ EOS
24
+
25
+ client_module.class_eval(custom_include, __FILE__, __LINE__)
26
+
27
+ client_module
28
+ end
29
+
30
+ # vanilla include
13
31
  def self.included(klass)
32
+ self.setup(klass)
33
+
34
+ super
35
+ end
36
+
37
+ def self.setup(klass, options={})
38
+ request_class = options[:request] || "Request"
39
+ collection_class = options[:collection] || "Collection"
40
+ model_class = options[:model] || "Model"
41
+
42
+ interface = options[:interface] || :class
43
+ interface_callback = (:class == interface) ? :inherited : :included
44
+
45
+ unless klass.name
46
+ raise ArgumentError, "can't turn anonymous class into a Cistern service"
47
+ end
48
+
14
49
  klass.class_eval <<-EOS, __FILE__, __LINE__
15
- module Collections
16
- include Cistern::Client::Collections
50
+ module Collections
51
+ include ::Cistern::Client::Collections
17
52
 
18
- def service
19
- #{klass.name}
20
- end
53
+ def service
54
+ #{klass.name}
21
55
  end
56
+ end
22
57
 
23
- def self.service
24
- #{klass.name}
25
- end
58
+ def self.service
59
+ #{klass.name}
60
+ end
26
61
 
27
- class Real
28
- def initialize(options={})
29
- end
62
+ class Real
63
+ def initialize(options={})
30
64
  end
65
+ end
31
66
 
32
- class Mock
33
- def initialize(options={})
34
- end
67
+ class Mock
68
+ def initialize(options={})
35
69
  end
70
+ end
36
71
 
37
- class Model
38
- include Cistern::Model
72
+ #{interface} #{model_class}
73
+ def self.#{interface_callback}(klass)
74
+ service.models << klass
39
75
 
40
- def self.inherited(klass)
41
- service.models << klass
42
- end
76
+ klass.send(:include, ::Cistern::Model)
77
+
78
+ super
79
+ end
43
80
 
44
- def self.service
45
- #{klass.name}
46
- end
81
+ def self.service
82
+ #{klass.name}
47
83
  end
84
+ end
48
85
 
49
- class Collection
50
- include Cistern::Collection
86
+ #{interface} #{collection_class}
87
+ include ::Cistern::Collection
51
88
 
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)
89
+ def self.#{interface_callback}(klass)
90
+ klass.send(:extend, Cistern::Attributes::ClassMethods)
91
+ klass.send(:extend, Cistern::Collection::ClassMethods)
92
+ klass.send(:include, Cistern::Attributes::InstanceMethods)
56
93
 
57
- service.collections << klass
58
- end
94
+ service.collections << klass
59
95
 
60
- def self.service
61
- #{klass.name}
62
- end
96
+ super
63
97
  end
64
98
 
65
- class Request
66
- include Cistern::Request
99
+ def self.service
100
+ #{klass.name}
101
+ end
102
+ end
67
103
 
68
- def self.inherited(klass)
69
- klass.extend(Cistern::Request::ClassMethods)
104
+ #{interface} #{request_class}
105
+ include ::Cistern::Request
70
106
 
71
- service.requests << klass
72
- end
107
+ def self.service
108
+ #{klass.name}
109
+ end
73
110
 
74
- def self.service
75
- #{klass.name}
76
- end
111
+ def self.#{interface_callback}(klass)
112
+ klass.extend(::Cistern::Request::ClassMethods)
77
113
 
78
- def _mock(*args)
79
- mock(*args)
80
- end
114
+ service.requests << klass
81
115
 
82
- def _real(*args)
83
- real(*args)
84
- end
116
+ super
85
117
  end
118
+
119
+ def _mock(*args)
120
+ mock(*args)
121
+ end
122
+
123
+ def _real(*args)
124
+ real(*args)
125
+ end
126
+ end
86
127
  EOS
87
128
 
88
129
  klass.send(:extend, Cistern::Client::ClassMethods)
@@ -97,8 +138,6 @@ module Cistern::Client
97
138
  klass::Real.send(:include, klass::Collections)
98
139
  klass::Real.send(:extend, Cistern::WaitFor)
99
140
  klass::Real.timeout_error = klass::Timeout
100
-
101
- super
102
141
  end
103
142
 
104
143
  module ClassMethods
@@ -1,5 +1,9 @@
1
1
  module Cistern::Request
2
2
  def self.service_request(service, klass, name)
3
+ unless klass.name
4
+ raise ArgumentError, "can't turn anonymous class into a Cistern request"
5
+ end
6
+
3
7
  service::Mock.module_eval <<-EOS, __FILE__, __LINE__
4
8
  def #{name}(*args)
5
9
  #{klass}.new(self)._mock(*args)
@@ -1,3 +1,3 @@
1
1
  module Cistern
2
- VERSION = "2.1.0"
2
+ VERSION = "2.2.1"
3
3
  end
@@ -0,0 +1,68 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe "client" do
4
+ context "with specific architecture" do
5
+ it "allows module-based interfaces" do
6
+ class ModuleClient
7
+ include Cistern::Client.with(interface: :module)
8
+ end
9
+
10
+ class ModuleClient::Shoot
11
+ include ModuleClient::Request
12
+
13
+ def real(mod)
14
+ mod % 9
15
+ end
16
+ end
17
+
18
+ class ModuleClient::Moon
19
+ include ModuleClient::Model
20
+
21
+ identity :on
22
+
23
+ def save
24
+ self.identity % 3
25
+ end
26
+ end
27
+
28
+ class ModuleClient::Moons
29
+ include ModuleClient::Collection
30
+
31
+ model ModuleClient::Moon
32
+
33
+ end
34
+
35
+ expect(
36
+ ModuleClient.new.shoot(12)
37
+ ).to eq(3)
38
+
39
+ expect(ModuleClient.collections).to contain_exactly(ModuleClient::Moons)
40
+ expect(ModuleClient.models).to contain_exactly(ModuleClient::Moon)
41
+ expect(ModuleClient.requests).to contain_exactly(ModuleClient::Shoot)
42
+
43
+ expect(
44
+ ModuleClient.new.moons.new(on: 5).save
45
+ ).to eq(2)
46
+ end
47
+
48
+ it "allows custom model interface" do
49
+ class AskClient
50
+ include Cistern::Client.with(model: "Ask", interface: :module)
51
+ end
52
+
53
+ class AskClient::Model
54
+ include AskClient::Ask
55
+
56
+ identity :id
57
+
58
+ def save
59
+ 9 % identity
60
+ end
61
+ end
62
+
63
+ expect(
64
+ AskClient.new.model(id: 9).save
65
+ ).to eq(0)
66
+ end
67
+ end
68
+ end
@@ -11,8 +11,6 @@ Bundler.require(:test)
11
11
  Cistern.deprecation_warnings = false
12
12
 
13
13
  RSpec.configure do |c|
14
- c.treat_symbols_as_metadata_keys_with_true_values = true
15
-
16
14
  if Kernel.respond_to?(:caller_locations)
17
15
  require File.expand_path('../../lib/cistern/coverage', __FILE__)
18
16
  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: 2.1.0
4
+ version: 2.2.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-09-29 00:00:00.000000000 Z
11
+ date: 2015-10-02 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: API client framework extracted from Fog
14
14
  email:
@@ -50,6 +50,7 @@ files:
50
50
  - lib/cistern/timeout.rb
51
51
  - lib/cistern/version.rb
52
52
  - lib/cistern/wait_for.rb
53
+ - spec/client_spec.rb
53
54
  - spec/collection_spec.rb
54
55
  - spec/dirty_spec.rb
55
56
  - spec/formatter_spec.rb
@@ -87,6 +88,7 @@ signing_key:
87
88
  specification_version: 4
88
89
  summary: API client framework
89
90
  test_files:
91
+ - spec/client_spec.rb
90
92
  - spec/collection_spec.rb
91
93
  - spec/dirty_spec.rb
92
94
  - spec/formatter_spec.rb