cistern 2.6.0 → 2.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +2 -3
- data/README.md +158 -80
- data/lib/cistern/client.rb +9 -9
- data/lib/cistern/request.rb +45 -15
- data/lib/cistern/singular.rb +1 -0
- data/lib/cistern/version.rb +1 -1
- data/spec/request_spec.rb +47 -25
- data/spec/singular_spec.rb +6 -0
- data/spec/spec_helper.rb +1 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: be9990e15cdccbe77ea1c27b5a6961fecd445129
|
4
|
+
data.tar.gz: d466f0e83e49c33fc9dce01eb713b9f1062e8f7e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dd4a3d7c95873a7fb999854846db84790273ad3366a018dc0e519d7708a13ec325a3a0d1b0bb4968f28cd6260dc4d72659c513513f56dfc2ec0b52ece8a9fb9d
|
7
|
+
data.tar.gz: 68ca70761102c30cca381a029184250a1750dc01d3c63626afe8b7ecd1929839497a8c6b55f995cef40ad8d5554b534987e1447f44eae567ae6c805cce82c2b5
|
data/CHANGELOG.md
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
-
## [
|
4
|
-
|
5
|
-
[Full Changelog](https://github.com/lanej/cistern/compare/v2.5.0...HEAD)
|
3
|
+
## [v2.6.0](https://github.com/lanej/cistern/tree/v2.6.0) (2016-07-26)
|
4
|
+
[Full Changelog](https://github.com/lanej/cistern/compare/v2.5.0...v2.6.0)
|
6
5
|
|
7
6
|
**Implemented enhancements:**
|
8
7
|
|
data/README.md
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# Cistern
|
2
2
|
|
3
|
+
[![Join the chat at https://gitter.im/lanej/cistern](https://badges.gitter.im/lanej/cistern.svg)](https://gitter.im/lanej/cistern?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
3
4
|
[![Build Status](https://secure.travis-ci.org/lanej/cistern.png)](http://travis-ci.org/lanej/cistern)
|
4
5
|
[![Dependencies](https://gemnasium.com/lanej/cistern.png)](https://gemnasium.com/lanej/cistern.png)
|
5
6
|
[![Gem Version](https://badge.fury.io/rb/cistern.svg)](http://badge.fury.io/rb/cistern)
|
@@ -9,40 +10,11 @@ Cistern helps you consistently build your API clients and faciliates building mo
|
|
9
10
|
|
10
11
|
## Usage
|
11
12
|
|
12
|
-
###
|
13
|
+
### Client
|
13
14
|
|
14
|
-
|
15
|
+
This represents the remote service that you are wrapping. It defines the client's namespace and initialization parameters.
|
15
16
|
|
16
|
-
|
17
|
-
|
18
|
-
In cistern `~> 3.0`, the default will be for `Request`, `Collection` and `Model` classes to instead include their respective `<service>::Client` modules.
|
19
|
-
|
20
|
-
If you want to be forwards-compatible today, you can configure your client by using `Cistern::Client.with`
|
21
|
-
|
22
|
-
```ruby
|
23
|
-
class Blog
|
24
|
-
include Cistern::Client.with(interface: :module)
|
25
|
-
end
|
26
|
-
```
|
27
|
-
|
28
|
-
Now request classes would look like:
|
29
|
-
|
30
|
-
```ruby
|
31
|
-
class Blog::GetPost
|
32
|
-
include Blog::Request
|
33
|
-
|
34
|
-
def real
|
35
|
-
"post"
|
36
|
-
end
|
37
|
-
end
|
38
|
-
```
|
39
|
-
|
40
|
-
|
41
|
-
### Service
|
42
|
-
|
43
|
-
This represents the remote service that you are wrapping. If the service name is `blog` then a good name is `Blog`.
|
44
|
-
|
45
|
-
Service initialization parameters are enumerated by `requires` and `recognizes`. Parameters defined using `recognizes` are optional.
|
17
|
+
Client initialization parameters are enumerated by `requires` and `recognizes`. Parameters defined using `recognizes` are optional.
|
46
18
|
|
47
19
|
```ruby
|
48
20
|
# lib/blog.rb
|
@@ -62,8 +34,7 @@ Blog.new(hmac_id: "1", url: "http://example.org")
|
|
62
34
|
Blog.new(hmac_id: "1")
|
63
35
|
```
|
64
36
|
|
65
|
-
Cistern will define for
|
66
|
-
new service.
|
37
|
+
Cistern will define for two namespaced classes, `Blog::Mock` and `Blog::Real`. Create the corresponding files and initialzers for your new service.
|
67
38
|
|
68
39
|
```ruby
|
69
40
|
# lib/blog/real.rb
|
@@ -105,74 +76,69 @@ real.is_a?(Blog::Real) # true
|
|
105
76
|
fake.is_a?(Blog::Mock) # true
|
106
77
|
```
|
107
78
|
|
108
|
-
###
|
79
|
+
### Requests
|
109
80
|
|
110
|
-
|
81
|
+
Requests are defined by subclassing `#{service}::Request`.
|
111
82
|
|
112
|
-
|
83
|
+
* `cistern` represents the associated `Blog` instance.
|
84
|
+
* `#call` represents the primary entrypoint. Invoked when calling `client#{request_method}`.
|
85
|
+
* `#dispatch` determines which method to call. (`#mock` or `#real`)
|
86
|
+
|
87
|
+
For example:
|
113
88
|
|
114
89
|
```ruby
|
115
|
-
|
116
|
-
|
117
|
-
# within a Resource
|
118
|
-
hash_stringify_keys({a: 1, b: 2}) #=> {'a' => 1, 'b' => 2}
|
119
|
-
```
|
90
|
+
class Blog::UpdatePost
|
91
|
+
include Blog::Request
|
120
92
|
|
121
|
-
|
93
|
+
def real(id, parameters)
|
94
|
+
cistern.connection.patch("/post/#{id}", parameters)
|
95
|
+
end
|
122
96
|
|
123
|
-
|
124
|
-
|
125
|
-
Cistern::Hash.slice({a: 1, b: 2, c: 3}, :a, :c) #=> {a: 1, c: 3}
|
126
|
-
# within a Resource
|
127
|
-
hash_slice({a: 1, b: 2, c: 3}, :a, :c) #=> {a: 1, c: 3}
|
128
|
-
```
|
97
|
+
def mock(id, parameters)
|
98
|
+
post = cistern.data[:posts].fetch(id)
|
129
99
|
|
130
|
-
|
100
|
+
post.merge!(stringify_keys(parameters))
|
131
101
|
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
# within a Resource
|
136
|
-
hash_except({a: 1, b: 2}, :a) #=> {b: 2}
|
102
|
+
response(post: post)
|
103
|
+
end
|
104
|
+
end
|
137
105
|
```
|
138
106
|
|
107
|
+
However, if you want to add some preprocessing to your request's arguments override `#call` and call `#dispatch`. You
|
108
|
+
can also alter the response method's signatures based on the arguments provided to `#dispatch`.
|
139
109
|
|
140
|
-
**#except!**
|
141
110
|
|
142
111
|
```ruby
|
143
|
-
|
144
|
-
|
145
|
-
# within a Resource
|
146
|
-
hash_except!({:a => 1, :b => 2}, :a) #=> {:b => 2}
|
147
|
-
```
|
112
|
+
class Blog::UpdatePost
|
113
|
+
include Blog::Request
|
148
114
|
|
115
|
+
attr_reader :parameters
|
149
116
|
|
150
|
-
|
117
|
+
def call(post_id, parameters)
|
118
|
+
@parameters = stringify_keys(parameters)
|
119
|
+
dispatch(Integer(post_id))
|
120
|
+
end
|
151
121
|
|
152
|
-
|
122
|
+
def real(id)
|
123
|
+
cistern.connection.patch("/post/#{id}", parameters)
|
124
|
+
end
|
153
125
|
|
154
|
-
|
126
|
+
def mock(id)
|
127
|
+
post = cistern.data[:posts].fetch(id)
|
155
128
|
|
156
|
-
|
157
|
-
class Blog::GetPost < Blog::Request
|
158
|
-
def real(params)
|
159
|
-
# make a real request
|
160
|
-
"i'm real"
|
161
|
-
end
|
129
|
+
post.merge!(parameters)
|
162
130
|
|
163
|
-
|
164
|
-
# return a fake response
|
165
|
-
"imposter!"
|
131
|
+
response(post: post)
|
166
132
|
end
|
167
133
|
end
|
168
|
-
|
169
|
-
Blog.new.get_post # "i'm real"
|
170
134
|
```
|
171
135
|
|
172
136
|
The `#cistern_method` function allows you to specify the name of the generated method.
|
173
137
|
|
174
138
|
```ruby
|
175
|
-
class Blog::GetPosts
|
139
|
+
class Blog::GetPosts
|
140
|
+
include Blog::Request
|
141
|
+
|
176
142
|
cistern_method :get_all_the_posts
|
177
143
|
|
178
144
|
def real(params)
|
@@ -264,7 +230,8 @@ Cistern attributes are designed to make your model flexible and developer friend
|
|
264
230
|
For example:
|
265
231
|
|
266
232
|
```ruby
|
267
|
-
class Blog::Post
|
233
|
+
class Blog::Post
|
234
|
+
include Blog::Model
|
268
235
|
identity :id, type: :integer
|
269
236
|
|
270
237
|
attribute :body
|
@@ -372,7 +339,8 @@ post.data.views #=> 3
|
|
372
339
|
* `load` consumes an Array of data and constructs matching `model` instances
|
373
340
|
|
374
341
|
```ruby
|
375
|
-
class Blog::Posts
|
342
|
+
class Blog::Posts
|
343
|
+
include Blog::Collection
|
376
344
|
|
377
345
|
attribute :count, type: :integer
|
378
346
|
|
@@ -415,7 +383,9 @@ There are two types of associations available.
|
|
415
383
|
* `has_many` references a collection of resources and defines a reader / writer.
|
416
384
|
|
417
385
|
```ruby
|
418
|
-
class Blog::Tag
|
386
|
+
class Blog::Tag
|
387
|
+
include Blog::Model
|
388
|
+
|
419
389
|
identity :id
|
420
390
|
attribute :author_id
|
421
391
|
|
@@ -435,7 +405,8 @@ tag.creator = blogs.author.get(name: 'phil')
|
|
435
405
|
tag.attributes[:creator] #=> { 'id' => 2, 'name' => 'phil' }
|
436
406
|
```
|
437
407
|
|
438
|
-
Foreign keys can be updated with association
|
408
|
+
Foreign keys can be updated with with the association writer by aliasing the original writer and accessing the
|
409
|
+
underlying attributes.
|
439
410
|
|
440
411
|
```ruby
|
441
412
|
Blog::Tag.class_eval do
|
@@ -505,6 +476,48 @@ class Blog
|
|
505
476
|
end
|
506
477
|
```
|
507
478
|
|
479
|
+
### Working with data
|
480
|
+
|
481
|
+
`Cistern::Hash` contains many useful functions for working with data normalization and transformation.
|
482
|
+
|
483
|
+
**#stringify_keys**
|
484
|
+
|
485
|
+
```ruby
|
486
|
+
# anywhere
|
487
|
+
Cistern::Hash.stringify_keys({a: 1, b: 2}) #=> {'a' => 1, 'b' => 2}
|
488
|
+
# within a Resource
|
489
|
+
hash_stringify_keys({a: 1, b: 2}) #=> {'a' => 1, 'b' => 2}
|
490
|
+
```
|
491
|
+
|
492
|
+
**#slice**
|
493
|
+
|
494
|
+
```ruby
|
495
|
+
# anywhere
|
496
|
+
Cistern::Hash.slice({a: 1, b: 2, c: 3}, :a, :c) #=> {a: 1, c: 3}
|
497
|
+
# within a Resource
|
498
|
+
hash_slice({a: 1, b: 2, c: 3}, :a, :c) #=> {a: 1, c: 3}
|
499
|
+
```
|
500
|
+
|
501
|
+
**#except**
|
502
|
+
|
503
|
+
```ruby
|
504
|
+
# anywhere
|
505
|
+
Cistern::Hash.except({a: 1, b: 2}, :a) #=> {b: 2}
|
506
|
+
# within a Resource
|
507
|
+
hash_except({a: 1, b: 2}, :a) #=> {b: 2}
|
508
|
+
```
|
509
|
+
|
510
|
+
|
511
|
+
**#except!**
|
512
|
+
|
513
|
+
```ruby
|
514
|
+
# same as #except but modify specified Hash in-place
|
515
|
+
Cistern::Hash.except!({:a => 1, :b => 2}, :a) #=> {:b => 2}
|
516
|
+
# within a Resource
|
517
|
+
hash_except!({:a => 1, :b => 2}, :a) #=> {:b => 2}
|
518
|
+
```
|
519
|
+
|
520
|
+
|
508
521
|
#### Storage
|
509
522
|
|
510
523
|
Currently supported storage backends are:
|
@@ -588,10 +601,75 @@ class Blog::GetPost
|
|
588
601
|
end
|
589
602
|
```
|
590
603
|
|
604
|
+
## ~> 3.0
|
605
|
+
|
606
|
+
### Request Dispatch
|
607
|
+
|
608
|
+
Default request interface passes through `#_mock` and `#_real` depending on the client mode.
|
609
|
+
|
610
|
+
```ruby
|
611
|
+
class Blog::GetPost
|
612
|
+
include Blog::Request
|
613
|
+
|
614
|
+
def setup(post_id, parameters)
|
615
|
+
[post_id, stringify_keys(parameters)]
|
616
|
+
end
|
617
|
+
|
618
|
+
def _mock(*args)
|
619
|
+
mock(*setup(*args))
|
620
|
+
end
|
621
|
+
|
622
|
+
def _real(post_id, parameters)
|
623
|
+
real(*setup(*args))
|
624
|
+
end
|
625
|
+
end
|
626
|
+
```
|
627
|
+
|
628
|
+
In cistern 3, requests pass through `#call` in both modes. `#dispatch` is responsible for determining the mode and
|
629
|
+
calling the appropriate method.
|
630
|
+
|
631
|
+
```ruby
|
632
|
+
class Blog::GetPost
|
633
|
+
include Blog::Request
|
634
|
+
|
635
|
+
def call(post_id, parameters)
|
636
|
+
normalized_parameters = stringify_keys(parameters)
|
637
|
+
dispatch(post_id, normalized_parameters)
|
638
|
+
end
|
639
|
+
end
|
640
|
+
```
|
641
|
+
|
642
|
+
### Client definition
|
643
|
+
|
644
|
+
Default resource definition is done by inheritance.
|
645
|
+
|
646
|
+
```ruby
|
647
|
+
class Blog::Post < Blog::Model
|
648
|
+
end
|
649
|
+
```
|
650
|
+
|
651
|
+
In cistern 3, resource definition is done by module inclusion.
|
652
|
+
|
653
|
+
```ruby
|
654
|
+
class Blog::Post
|
655
|
+
include Blog::Post
|
656
|
+
end
|
657
|
+
```
|
658
|
+
|
659
|
+
Prepare for cistern 3 by using `Cistern::Client.with(interface: :module)` when defining the client.
|
660
|
+
|
661
|
+
```ruby
|
662
|
+
class Blog
|
663
|
+
include Cistern::Client.with(interface: :module)
|
664
|
+
end
|
665
|
+
```
|
666
|
+
|
591
667
|
## Examples
|
592
668
|
|
593
669
|
* [zendesk2](https://github.com/lanej/zendesk2)
|
594
670
|
* [you_track](https://github.com/lanej/you_track)
|
671
|
+
* [ey-core](https://github.com/engineyard/core-client-rb)
|
672
|
+
|
595
673
|
|
596
674
|
## Releasing
|
597
675
|
|
data/lib/cistern/client.rb
CHANGED
@@ -44,7 +44,7 @@ module Cistern::Client
|
|
44
44
|
|
45
45
|
if interface == :class
|
46
46
|
Cistern.deprecation(
|
47
|
-
%q{class' interface is deprecated. Use `include Cistern::Client.with(interface: :module). See https://github.com/lanej/cistern#custom-architecture},
|
47
|
+
%q{'class' interface is deprecated. Use `include Cistern::Client.with(interface: :module). See https://github.com/lanej/cistern#custom-architecture},
|
48
48
|
caller[2],
|
49
49
|
)
|
50
50
|
end
|
@@ -85,11 +85,19 @@ module Cistern::Client
|
|
85
85
|
class Real
|
86
86
|
def initialize(options={})
|
87
87
|
end
|
88
|
+
|
89
|
+
def mocking?
|
90
|
+
false
|
91
|
+
end
|
88
92
|
end
|
89
93
|
|
90
94
|
class Mock
|
91
95
|
def initialize(options={})
|
92
96
|
end
|
97
|
+
|
98
|
+
def mocking?
|
99
|
+
true
|
100
|
+
end
|
93
101
|
end
|
94
102
|
|
95
103
|
#{interface} #{model_class}
|
@@ -184,14 +192,6 @@ module Cistern::Client
|
|
184
192
|
|
185
193
|
super
|
186
194
|
end
|
187
|
-
|
188
|
-
def _mock(*args)
|
189
|
-
mock(*args)
|
190
|
-
end
|
191
|
-
|
192
|
-
def _real(*args)
|
193
|
-
real(*args)
|
194
|
-
end
|
195
195
|
end
|
196
196
|
EOS
|
197
197
|
|
data/lib/cistern/request.rb
CHANGED
@@ -1,22 +1,35 @@
|
|
1
1
|
module Cistern::Request
|
2
2
|
include Cistern::HashSupport
|
3
3
|
|
4
|
+
module ClassMethods
|
5
|
+
# @deprecated Use {#cistern_method} instead
|
6
|
+
def service_method(name = nil)
|
7
|
+
Cistern.deprecation(
|
8
|
+
'#service_method is deprecated. Please use #cistern_method',
|
9
|
+
caller[0]
|
10
|
+
)
|
11
|
+
@_cistern_method ||= name
|
12
|
+
end
|
13
|
+
|
14
|
+
def cistern_method(name = nil)
|
15
|
+
@_cistern_method ||= name
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
4
19
|
def self.cistern_request(cistern, klass, name)
|
5
20
|
unless klass.name || klass.cistern_method
|
6
21
|
fail ArgumentError, "can't turn anonymous class into a Cistern request"
|
7
22
|
end
|
8
23
|
|
9
|
-
|
24
|
+
method = <<-EOS
|
10
25
|
def #{name}(*args)
|
11
|
-
#{klass}.new(self).
|
26
|
+
#{klass}.new(self).call(*args)
|
12
27
|
end
|
13
28
|
EOS
|
14
29
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
end
|
19
|
-
EOS
|
30
|
+
|
31
|
+
cistern::Mock.module_eval method, __FILE__, __LINE__
|
32
|
+
cistern::Real.module_eval method, __FILE__, __LINE__
|
20
33
|
end
|
21
34
|
|
22
35
|
def self.service_request(*args)
|
@@ -41,18 +54,35 @@ module Cistern::Request
|
|
41
54
|
@cistern = cistern
|
42
55
|
end
|
43
56
|
|
44
|
-
|
45
|
-
|
46
|
-
|
57
|
+
def call(*args)
|
58
|
+
dispatch(*args)
|
59
|
+
end
|
60
|
+
|
61
|
+
def real(*)
|
62
|
+
raise NotImplementedError
|
63
|
+
end
|
64
|
+
|
65
|
+
def mock(*)
|
66
|
+
raise NotImplementedError
|
67
|
+
end
|
68
|
+
|
69
|
+
protected
|
70
|
+
|
71
|
+
# @fixme remove _{mock,real} methods and call {mock,real} directly before 3.0 release.
|
72
|
+
def dispatch(*args)
|
73
|
+
to = cistern.mocking? ? :mock : :real
|
74
|
+
|
75
|
+
legacy_method = :"_#{to}"
|
76
|
+
|
77
|
+
if respond_to?(legacy_method)
|
47
78
|
Cistern.deprecation(
|
48
|
-
'#
|
79
|
+
'#_mock is deprecated. Please use #mock and/or #call. See https://github.com/lanej/cistern#request-dispatch',
|
49
80
|
caller[0]
|
50
81
|
)
|
51
|
-
@_cistern_method ||= name
|
52
|
-
end
|
53
82
|
|
54
|
-
|
55
|
-
|
83
|
+
public_send(legacy_method, *args)
|
84
|
+
else
|
85
|
+
public_send(to, *args)
|
56
86
|
end
|
57
87
|
end
|
58
88
|
end
|
data/lib/cistern/singular.rb
CHANGED
@@ -15,6 +15,7 @@ module Cistern::Singular
|
|
15
15
|
klass.send(:extend, Cistern::Attributes::ClassMethods)
|
16
16
|
klass.send(:include, Cistern::Attributes::InstanceMethods)
|
17
17
|
klass.send(:extend, Cistern::Model::ClassMethods)
|
18
|
+
klass.send(:extend, Cistern::Associations)
|
18
19
|
end
|
19
20
|
|
20
21
|
def collection
|
data/lib/cistern/version.rb
CHANGED
data/spec/request_spec.rb
CHANGED
@@ -1,57 +1,79 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe 'Cistern::Request' do
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
4
|
+
before {
|
5
|
+
Sample.class_eval do
|
6
|
+
recognizes :key
|
7
|
+
end
|
8
8
|
|
9
|
-
|
9
|
+
Sample::Real.class_eval do
|
10
10
|
attr_reader :service_args
|
11
11
|
|
12
12
|
def initialize(*args)
|
13
13
|
@service_args = args
|
14
14
|
end
|
15
15
|
end
|
16
|
-
|
16
|
+
}
|
17
17
|
|
18
|
-
#
|
19
|
-
|
20
|
-
|
18
|
+
describe '#cistern_method' do
|
19
|
+
it 'remaps the client request method' do
|
20
|
+
class ListSamples < Sample::Request
|
21
|
+
cistern_method :list_all_samples
|
22
|
+
end
|
21
23
|
|
22
|
-
|
23
|
-
|
24
|
+
expect(Sample.new).to respond_to(:list_all_samples)
|
25
|
+
expect(Sample.new).not_to respond_to(:list_samples)
|
24
26
|
end
|
27
|
+
end
|
25
28
|
|
26
|
-
|
27
|
-
|
29
|
+
it 'calls the appropriate method' do
|
30
|
+
class GetSamples < Sample::Request
|
31
|
+
def real(*args)
|
32
|
+
cistern.service_args + args + ['real']
|
33
|
+
end
|
34
|
+
|
35
|
+
def mock(*args)
|
36
|
+
args + ['mock']
|
37
|
+
end
|
28
38
|
end
|
29
|
-
end
|
30
39
|
|
31
|
-
|
32
|
-
expect(
|
33
|
-
expect(
|
34
|
-
expect(RequestService::Mock.new.list_all_samples('sample3')).to eq(%w(sample3 mock))
|
40
|
+
expect(Sample.new.get_samples('sample1')).to eq([{}, 'sample1', 'real'])
|
41
|
+
expect(Sample::Real.new.get_samples('sample2')).to eq(%w(sample2 real))
|
42
|
+
expect(Sample::Mock.new.get_samples('sample3')).to eq(%w(sample3 mock))
|
35
43
|
|
36
44
|
# service access
|
37
|
-
expect(
|
45
|
+
expect(Sample.new(key: 'value').get_samples('stat')).to eq([{ key: 'value' }, 'stat', 'real'])
|
38
46
|
end
|
39
47
|
|
40
48
|
describe 'deprecation', :deprecated do
|
41
|
-
|
42
|
-
|
49
|
+
it 'calls _mock and _real if present' do
|
50
|
+
class Sample::ListDeprecations < Sample::Request
|
51
|
+
def _mock
|
52
|
+
:_mock
|
53
|
+
end
|
54
|
+
|
55
|
+
def real
|
56
|
+
:real
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
actual = Sample.new.list_deprecations
|
61
|
+
expect(actual).to eq(:real)
|
62
|
+
|
63
|
+
Sample.mock!
|
64
|
+
|
65
|
+
actual = Sample.new.list_deprecations
|
66
|
+
expect(actual).to eq(:_mock)
|
43
67
|
end
|
44
68
|
|
45
69
|
it 'responds to #service' do
|
46
|
-
class ListDeprecations <
|
47
|
-
service_method :list_deprecations
|
48
|
-
|
70
|
+
class Sample::ListDeprecations < Sample::Request
|
49
71
|
def real
|
50
72
|
self
|
51
73
|
end
|
52
74
|
end
|
53
75
|
|
54
|
-
sample =
|
76
|
+
sample = Sample.new.list_deprecations
|
55
77
|
expect(sample.service).to eq(sample.cistern)
|
56
78
|
end
|
57
79
|
end
|
data/spec/singular_spec.rb
CHANGED
@@ -6,6 +6,8 @@ describe 'Cistern::Singular' do
|
|
6
6
|
attribute :name, type: :string
|
7
7
|
attribute :count, type: :number
|
8
8
|
|
9
|
+
belongs_to :entity, -> { cistern.settings(name: '1') }
|
10
|
+
|
9
11
|
def save
|
10
12
|
result = @@settings = attributes.merge(dirty_attributes)
|
11
13
|
|
@@ -32,6 +34,10 @@ describe 'Cistern::Singular' do
|
|
32
34
|
end
|
33
35
|
end
|
34
36
|
|
37
|
+
it 'allows associations' do
|
38
|
+
expect(service.settings.load.entity.name).to eq('1')
|
39
|
+
end
|
40
|
+
|
35
41
|
it 'reloads' do
|
36
42
|
singular = service.settings(count: 0)
|
37
43
|
|
data/spec/spec_helper.rb
CHANGED
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.
|
4
|
+
version: 2.7.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: 2016-
|
11
|
+
date: 2016-08-10 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: API client framework extracted from Fog
|
14
14
|
email:
|