cistern 0.12.3 → 1.0.0.pre

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: 4f214af97e02bf01188735dc497174c917a65c8f
4
- data.tar.gz: ba7b5558199ebb2b11a16890c62e4e4b916d9ab9
3
+ metadata.gz: d450addd353c421e2096a7236b9df93588d33dd0
4
+ data.tar.gz: 1eed93cace8518f20b98d0576a672c2e32f825aa
5
5
  SHA512:
6
- metadata.gz: 05b899eb55fb736798eb495edce085e5c4eabaa92d5778c2fc7fd81959ff55f5b64003daa13a8751b543d119dd536bc2f81e5d225f93ed34bc3824082001ef38
7
- data.tar.gz: fbd8908440fdaff653e46cebe6c29480b353568ffc24bdcd4372b18ce1cec18a6f6b996db48e1d2ac39c9e5310236442e86487f13fe9abc9b98f7e73d884402e
6
+ metadata.gz: 787f6a8105570622d8846676e87f04bdeb53a15d88ffe6e18ba54afa264b7aeb4c893cfdafd1cf924c3ebdbfda6480aab88b32580bb334283cfec801cad12d17
7
+ data.tar.gz: abd365799a52bc3192712595b7574b8aad97975a66535bc78f073442e32c43c73b4ff8bfb167e71410ad0a567cc775914acc9f9ac1dbf8f979a6734eeb95ccde
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", "~> 3.3"
11
+ gem "rspec", "~> 2.99"
12
12
  gem "redis-namespace", "~> 1.4", "< 1.5"
13
13
  gem "codeclimate-test-reporter", require: false
14
14
  end
data/README.md CHANGED
@@ -58,29 +58,6 @@ 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
-
84
61
  #### Models and Collections
85
62
 
86
63
  Models and collections have declaration semantics similar to requests. Models and collections are enumerated via `model` and `collection` respectively.
@@ -231,7 +208,7 @@ Patient::Mock.store_in(:hash)
231
208
 
232
209
  ### Model
233
210
 
234
- * `connection` represents the associated `Foo::Client` instance.
211
+ * `service` represents the associated `Foo::Client` instance.
235
212
  * `collection` represents the related collection (if applicable)
236
213
 
237
214
  Example
@@ -248,7 +225,7 @@ class Foo::Client::Bar < Cistern::Model
248
225
  params = {
249
226
  "id" => self.identity
250
227
  }
251
- self.connection.destroy_bar(params).body["request"]
228
+ self.service.destroy_bar(params).body["request"]
252
229
  end
253
230
 
254
231
  def save
@@ -262,11 +239,11 @@ class Foo::Client::Bar < Cistern::Model
262
239
  }
263
240
 
264
241
  if new_record?
265
- merge_attributes(connection.create_bar(params).body["bar"])
242
+ merge_attributes(service.create_bar(params).body["bar"])
266
243
  else
267
244
  requires :identity
268
245
 
269
- merge_attributes(connection.update_bar(params).body["bar"])
246
+ merge_attributes(service.update_bar(params).body["bar"])
270
247
  end
271
248
  end
272
249
  end
@@ -309,7 +286,7 @@ class Foo::Client::Bars < Cistern::Collection
309
286
  model Foo::Client::Bar
310
287
 
311
288
  def all(params = {})
312
- response = connection.get_bars(params)
289
+ response = service.get_bars(params)
313
290
 
314
291
  data = response.body
315
292
 
@@ -323,11 +300,11 @@ class Foo::Client::Bars < Cistern::Collection
323
300
  }
324
301
  params.merge!("location" => options[:location]) if options.key?(:location)
325
302
 
326
- connection.requests.new(connection.discover_bar(params).body["request"])
303
+ service.requests.new(service.discover_bar(params).body["request"])
327
304
  end
328
305
 
329
306
  def get(id)
330
- if data = connection.get_bar("id" => id).body["bar"]
307
+ if data = service.get_bar("id" => id).body["bar"]
331
308
  new(data)
332
309
  else
333
310
  nil
@@ -9,6 +9,7 @@ module Cistern
9
9
  Timeout = Class.new(Error)
10
10
 
11
11
  require 'cistern/hash'
12
+ require 'cistern/string'
12
13
  require 'cistern/mock'
13
14
  require 'cistern/wait_for'
14
15
  require 'cistern/attributes'
@@ -16,11 +17,10 @@ module Cistern
16
17
  require 'cistern/model'
17
18
  require 'cistern/service'
18
19
  require 'cistern/singular'
20
+ require 'cistern/request'
19
21
  require 'cistern/data'
20
22
  require 'cistern/data/hash'
21
23
  require 'cistern/data/redis'
22
- require 'cistern/request'
23
- require 'cistern/string'
24
24
 
25
25
  extend WaitFor
26
26
 
@@ -121,19 +121,9 @@ module Cistern::Attributes
121
121
  def read_attribute(name)
122
122
  options = self.class.attributes[name] || {}
123
123
  # record the attribute was accessed
124
- begin
125
- self.class.attributes[name.to_s.to_sym][:coverage_hits] += 1
126
- rescue
127
- nil
128
- end
129
-
130
- default = options[:default]
131
-
132
- unless default.nil?
133
- default = Marshal.load(Marshal.dump(default))
134
- end
124
+ self.class.attributes[name.to_s.to_sym][:coverage_hits] += 1 rescue nil
135
125
 
136
- attributes.fetch(name.to_s.to_sym, default)
126
+ attributes.fetch(name.to_s.to_sym, options[:default])
137
127
  end
138
128
 
139
129
  def write_attribute(name, value)
@@ -183,39 +173,26 @@ module Cistern::Attributes
183
173
  end
184
174
 
185
175
  def merge_attributes(new_attributes = {})
186
- protected_methods = (Cistern::Model.instance_methods - [:connection, :identity, :collection])
187
- ignored_attributes = self.class.ignored_attributes
188
- class_attributes = self.class.attributes
189
- class_aliases = self.class.aliases
190
-
191
176
  new_attributes.each do |_key, value|
192
- string_key = _key.kind_of?(String) ? _key : _key.to_s
193
- symbol_key = case _key
194
- when String
195
- _key.to_sym
196
- when Symbol
197
- _key
198
- else
199
- string_key.to_sym
200
- end
201
-
177
+ key = _key.to_s.to_sym
202
178
  # find nested paths
203
- value.is_a?(::Hash) && class_attributes.each do |name, options|
204
- if options[:squash] && options[:squash].first == string_key
205
- send("#{name}=", {symbol_key => value})
179
+ value.is_a?(::Hash) && self.class.attributes.each do |name, options|
180
+ if (options[:squash] || []).first == key.to_s
181
+ send("#{name}=", {key => value})
206
182
  end
207
183
  end
208
184
 
209
- unless ignored_attributes.include?(symbol_key)
210
- if class_aliases.has_key?(symbol_key)
211
- class_aliases[symbol_key].each do |aliased_key|
185
+ unless self.class.ignored_attributes.include?(key)
186
+ if self.class.aliases.has_key?(key)
187
+ self.class.aliases[key].each do |aliased_key|
212
188
  send("#{aliased_key}=", value)
213
189
  end
214
190
  end
215
191
 
216
- assignment_method = "#{string_key}="
217
- if !protected_methods.include?(symbol_key) && self.respond_to?(assignment_method, true)
218
- send(assignment_method, value)
192
+ protected_methods = Cistern::Model.instance_methods - [:service, :identity, :collection]
193
+
194
+ if !protected_methods.include?(key) && self.respond_to?("#{key}=", true)
195
+ send("#{key}=", value)
219
196
  end
220
197
  end
221
198
  end
@@ -259,7 +236,7 @@ module Cistern::Attributes
259
236
  protected
260
237
 
261
238
  def missing_attributes(args)
262
- ([:connection] | args).select{|arg| send("#{arg}").nil?}
239
+ ([:service] | args).select{|arg| send("#{arg}").nil?}
263
240
  end
264
241
 
265
242
  def changed!(attribute, from, to)
@@ -1,6 +1,4 @@
1
- class Cistern::Collection
2
- extend Cistern::Attributes::ClassMethods
3
- include Cistern::Attributes::InstanceMethods
1
+ module Cistern::Collection
4
2
 
5
3
  BLACKLISTED_ARRAY_METHODS = [
6
4
  :compact!, :flatten!, :reject!, :reverse!, :rotate!, :map!,
@@ -8,15 +6,21 @@ class Cistern::Collection
8
6
  :keep_if, :pop, :shift, :delete_at, :compact
9
7
  ].to_set # :nodoc:
10
8
 
11
- attr_accessor :records, :loaded, :connection
9
+ def self.service_collection(service, klass)
10
+ plural_name = Cistern::String.underscore(Cistern::String.demodulize(klass.name))
12
11
 
13
- alias service connection
12
+ service.const_get(:Collections).module_eval <<-EOS, __FILE__, __LINE__
13
+ def #{plural_name}(attributes={})
14
+ #{klass.name}.new(attributes.merge(service: self))
15
+ end
16
+ EOS
17
+ end
14
18
 
15
- def self.model(new_model=nil)
16
- if new_model == nil
17
- @model
18
- else
19
- @model = new_model
19
+ attr_accessor :records, :loaded, :service
20
+
21
+ module ClassMethods
22
+ def model(new_model=nil)
23
+ @model ||= new_model
20
24
  end
21
25
  end
22
26
 
@@ -75,7 +79,7 @@ class Cistern::Collection
75
79
  model.new(
76
80
  {
77
81
  :collection => self,
78
- :connection => connection,
82
+ :service => service,
79
83
  }.merge(attributes)
80
84
  )
81
85
  end
@@ -7,10 +7,6 @@ module Cistern::Formatter
7
7
  Cistern::Formatter::AwesomePrint
8
8
  elsif defined?(::Formatador)
9
9
  Cistern::Formatter::Formatador
10
- else
11
- Cistern::Formatter::Default
12
10
  end
13
11
  end
14
12
  end
15
-
16
- require 'cistern/formatter/default'
@@ -1,13 +1,19 @@
1
- class Cistern::Model
2
- extend Cistern::Attributes::ClassMethods
1
+ module Cistern::Model
3
2
  include Cistern::Attributes::InstanceMethods
4
3
 
5
- attr_accessor :collection, :connection
4
+ def self.included(klass)
5
+ klass.send(:extend, Cistern::Attributes::ClassMethods)
6
+ klass.send(:include, Cistern::Attributes::InstanceMethods)
7
+ end
6
8
 
7
- alias service connection
9
+ attr_accessor :collection, :service
8
10
 
9
11
  def inspect
10
- Cistern.formatter.call(self)
12
+ if Cistern.formatter
13
+ Cistern.formatter.call(self)
14
+ else
15
+ "#<#{self.class} #{self.identity}"
16
+ end
11
17
  end
12
18
 
13
19
  def initialize(attributes={})
@@ -50,15 +56,15 @@ class Cistern::Model
50
56
  end
51
57
  end
52
58
 
53
- def service
54
- self.connection ? self.connection.class : Cistern
59
+ def wait_for(timeout = self.service_class.timeout, interval = self.service_class.poll_interval, &block)
60
+ service_class.wait_for(timeout, interval) { reload && block.call(self) }
55
61
  end
56
62
 
57
- def wait_for(timeout = self.service.timeout, interval = self.service.poll_interval, &block)
58
- service.wait_for(timeout, interval) { reload && block.call(self) }
63
+ def wait_for!(timeout = self.service_class.timeout, interval = self.service_class.poll_interval, &block)
64
+ service_class.wait_for!(timeout, interval) { reload && block.call(self) }
59
65
  end
60
66
 
61
- def wait_for!(timeout = self.service.timeout, interval = self.service.poll_interval, &block)
62
- service.wait_for!(timeout, interval) { reload && block.call(self) }
67
+ def service_class
68
+ self.service ? self.service.class : Cistern
63
69
  end
64
70
  end
@@ -1,41 +1,28 @@
1
- class Cistern::Request
2
- def self.register(service, klass, method)
3
- service.requests << [method, {class: klass, method: method, new: true}]
4
- end
1
+ module Cistern::Request
2
+ def self.service_request(service, klass)
3
+ request = klass.request_name || Cistern::String.camelize(klass.name)
5
4
 
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
5
+ service::Mock.module_eval <<-EOS, __FILE__, __LINE__
6
+ def #{request}(*args)
7
+ #{klass}.new(self).mock(*args)
8
+ end
9
+ EOS
13
10
 
14
- def self.service_method
15
- @service_method
11
+ service::Real.module_eval <<-EOS, __FILE__, __LINE__
12
+ def #{request}(*args)
13
+ #{klass}.new(self).real(*args)
14
+ end
15
+ EOS
16
16
  end
17
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
18
+ attr_reader :service
33
19
 
34
- def real(*args, &block)
35
- raise NotImplementedError
20
+ def initialize(service)
21
+ @service = service
36
22
  end
37
23
 
38
- def mock(*args, &block)
39
- Cistern::Mock.not_implemented(self.class.service_method)
24
+ module ClassMethods
25
+ def request_name
26
+ end
40
27
  end
41
28
  end
@@ -42,6 +42,44 @@ class Cistern::Service
42
42
  def initialize(options={})
43
43
  end
44
44
  end
45
+
46
+ class Model
47
+ include Cistern::Model
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.extend(Cistern::Attributes::ClassMethods)
59
+ klass.extend(Cistern::Collection::ClassMethods)
60
+ klass.include(Cistern::Attributes::InstanceMethods)
61
+
62
+ Cistern::Collection.service_collection(service, 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
+ Cistern::Request.service_request(service, klass)
77
+ end
78
+
79
+ def self.service
80
+ #{klass.name}
81
+ end
82
+ end
45
83
  EOS
46
84
 
47
85
  klass.send(:const_set, :Timeout, Class.new(Cistern::Error))
@@ -57,30 +95,6 @@ class Cistern::Service
57
95
  klass::Real.timeout_error = klass::Timeout
58
96
  end
59
97
 
60
- def collection_path(collection_path = nil)
61
- if collection_path
62
- @collection_path = collection_path
63
- else
64
- @collection_path
65
- end
66
- end
67
-
68
- def model_path(model_path = nil)
69
- if model_path
70
- @model_path = model_path
71
- else
72
- @model_path
73
- end
74
- end
75
-
76
- def request_path(request_path = nil)
77
- if request_path
78
- @request_path = request_path
79
- else
80
- @request_path
81
- end
82
- end
83
-
84
98
  def collections
85
99
  @collections ||= []
86
100
  end
@@ -109,22 +123,10 @@ class Cistern::Service
109
123
  self.recognized_arguments.concat(args)
110
124
  end
111
125
 
112
- def model(model_name, options={})
113
- models << [model_name, options]
114
- end
115
-
116
126
  def mocked_requests
117
127
  @mocked_requests ||= []
118
128
  end
119
129
 
120
- def request(request_name, options={})
121
- requests << [request_name, options]
122
- end
123
-
124
- def collection(collection_name, options={})
125
- collections << [collection_name, options]
126
- end
127
-
128
130
  def validate_options(options={})
129
131
  required_options = Cistern::Hash.slice(options, *required_arguments)
130
132
 
@@ -141,91 +143,8 @@ class Cistern::Service
141
143
  end
142
144
  end
143
145
 
144
- def setup_requirements
145
- @required ||= false
146
- unless @required
147
-
148
- # setup models
149
- models.each do |model, options|
150
- unless options[:require] == false
151
- require(options[:require] || File.join(@model_path, model.to_s))
152
- end
153
-
154
- class_name = options[:class] || model.to_s.split("_").map(&:capitalize).join
155
- singular_name = options[:model] || model.to_s.gsub("/", "_")
156
-
157
- self.const_get(:Collections).module_eval <<-EOS, __FILE__, __LINE__
158
- def #{singular_name}(attributes={})
159
- #{service}::#{class_name}.new({connection: self}.merge(attributes))
160
- end
161
- EOS
162
- end
163
-
164
- # setup requests
165
- requests.each do |request, options|
166
- unless (options[:require] == false) || options[:new] || service::Real.method_defined?(request.to_s)
167
- require(options[:require] || File.join(@request_path, request.to_s))
168
- end
169
-
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)
194
- mocked_requests << request
195
- else
196
- service::Mock.module_eval <<-EOS, __FILE__, __LINE__
197
- def #{request}(*args)
198
- Cistern::Mock.not_implemented(request)
199
- end
200
- EOS
201
- end
202
- end
203
-
204
- # setup collections
205
- collections.each do |collection, options|
206
- unless false == options[:require]
207
- require(options[:require] || File.join(@collection_path || @model_path, collection.to_s))
208
- end
209
-
210
- class_name = collection.to_s.
211
- split("/").map(&:capitalize).join("::").split("_").
212
- map { |s| "#{s[0].upcase}#{s[1..-1]}" }.join
213
- plural_name = options[:collection] || collection.to_s.gsub("/", "_")
214
-
215
- self.const_get(:Collections).module_eval <<-EOS, __FILE__, __LINE__
216
- def #{plural_name}(attributes={})
217
- #{service}::#{class_name}.new({connection: self}.merge(attributes))
218
- end
219
- EOS
220
- end
221
-
222
- @required = true
223
- end
224
- end
225
-
226
146
  def new(options={})
227
147
  validate_options(options)
228
- setup_requirements
229
148
 
230
149
  self.const_get(self.mocking? ? :Mock : :Real).new(options)
231
150
  end
@@ -2,7 +2,7 @@ class Cistern::Singular
2
2
  extend Cistern::Attributes::ClassMethods
3
3
  include Cistern::Attributes::InstanceMethods
4
4
 
5
- attr_accessor :connection
5
+ attr_accessor :service
6
6
 
7
7
  def inspect
8
8
  if Cistern.formatter
@@ -1,5 +1,20 @@
1
1
  class Cistern::String
2
- # stolen from activesupport/lib/active_support/inflector/methods.rb, line 198
2
+ def self.camelize(string)
3
+ string.gsub(/[A-Z]+/) { |w| "_#{w.downcase}" }.gsub(/^_/, "")
4
+ end
5
+
6
+ # File activesupport/lib/active_support/inflector/methods.rb, line 90
7
+ def self.underscore(camel_cased_word)
8
+ word = camel_cased_word.to_s.gsub('::', '/')
9
+ #word.gsub!(/(?:([A-Za-z\d])|^)(#{inflections.acronym_regex})(?=\b|[^a-z])/) { "#{$1}#{$1 && '_'}#{$2.downcase}" }
10
+ word.gsub!(/([A-Z\d]+)([A-Z][a-z])/,'\1_\2')
11
+ word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
12
+ word.tr!("-", "_")
13
+ word.downcase!
14
+ word
15
+ end
16
+
17
+ # File activesupport/lib/active_support/inflector/methods.rb, line 168
3
18
  def self.demodulize(path)
4
19
  path = path.to_s
5
20
  if i = path.rindex('::')
@@ -9,15 +24,8 @@ class Cistern::String
9
24
  end
10
25
  end
11
26
 
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
27
+ # @todo omg so bad
28
+ def self.pluralize(string)
29
+ "#{string}s"
22
30
  end
23
31
  end
@@ -1,3 +1,3 @@
1
1
  module Cistern
2
- VERSION = "0.12.3"
2
+ VERSION = "1.0.0.pre"
3
3
  end
@@ -1,13 +1,12 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe "Cistern::Collection" do
4
-
5
- class SampleCollectionModel < Cistern::Model
4
+ class SampleCollectionModel < Sample::Model
6
5
  identity :id
7
6
  attribute :name
8
7
  end
9
8
 
10
- class SampleCollection < Cistern::Collection
9
+ class SampleCollection < Sample::Collection
11
10
  model SampleCollectionModel
12
11
 
13
12
  def all
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe "Cistern::Model#dirty" do
4
- class DirtySpec < Cistern::Model
4
+ class DirtySpec < Sample::Model
5
5
  identity :id
6
6
 
7
7
  attribute :name
@@ -1,75 +1,41 @@
1
1
  require 'spec_helper'
2
2
 
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"}])
18
- end
19
- end
20
-
21
- describe Cistern::Formatter::Default do
22
- before { Cistern.formatter = described_class }
23
-
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
- )
30
-
31
- Anon.inspect
32
- end
33
-
34
- it "formats a collection" do
35
- expect(
36
- Inspectors.new.all.inspect
37
- ).to match(
38
- /<Inspectors:0x[a-z0-9]+> {} records/
39
- )
3
+ describe "#inspect" do
4
+ class Inspector < Sample::Model
5
+ identity :id
6
+ attribute :name
40
7
  end
41
- end
42
8
 
43
- describe Cistern::Formatter::AwesomePrint do
44
- before { Cistern.formatter = described_class }
9
+ class Inspectors < Sample::Collection
10
+ model Inspector
45
11
 
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
- )
12
+ def all(options={})
13
+ merge_attributes(options)
14
+ self.load([{id: 1, name: "2"},{id: 3, name: "4"}])
15
+ end
52
16
  end
53
17
 
54
- it "formats a collection" do
55
- expect(Inspectors.new.all.inspect).to match(/Inspectors\s+{.*}$/m) # close enough
56
- end
57
- end
18
+ describe "Cistern::Model" do
19
+ it "should use awesome_print" do
20
+ Cistern.formatter = Cistern::Formatter::AwesomePrint
58
21
 
59
- describe Cistern::Formatter::Formatador do
60
- before { Cistern.formatter = described_class }
22
+ Inspector.new(id: 1, name: "name").inspect.match /(?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})/
23
+ end
61
24
 
62
- it "formats a model" do
63
- Cistern.formatter = Cistern::Formatter::Formatador
25
+ it "should use formatador" do
26
+ Cistern.formatter = Cistern::Formatter::Formatador
64
27
 
65
- expect(Inspector.new(id: 1, name: "name").inspect).to eq(%q{ <Inspector
28
+ expect(Inspector.new(id: 1, name: "name").inspect).to eq(%q{ <Inspector
66
29
  id=1,
67
30
  name="name"
68
31
  >})
32
+ end
69
33
  end
70
34
 
71
- it "formats a collection" do
72
- expect(Inspectors.new.all.inspect).to eq(%q{ <Inspectors
35
+ describe "Cistern::Collection" do
36
+ it "should use formatador" do
37
+ Cistern.formatter = Cistern::Formatter::Formatador
38
+ expect(Inspectors.new.all.inspect).to eq(%q{ <Inspectors
73
39
  [
74
40
  <Inspector
75
41
  id=1,
@@ -81,5 +47,11 @@ describe Cistern::Formatter::Formatador do
81
47
  >
82
48
  ]
83
49
  >})
50
+ end
51
+
52
+ it "should use awesome_print" do
53
+ Cistern.formatter = Cistern::Formatter::AwesomePrint
54
+ expect(Inspectors.new.all.inspect).to match(/Inspectors\s+{.*}$/m) # close enough
55
+ end
84
56
  end
85
57
  end
@@ -1,37 +1,31 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe 'mock data' do
4
- class Patient < Cistern::Service
5
- request :diagnosis
6
- request :treat
7
-
8
- class Real
9
- def diagnosis(options={})
10
- end
4
+ class Diagnosis < Sample::Request
5
+ def real(diagnosis)
6
+ end
11
7
 
12
- def treat(options={})
13
- end
8
+ def mock(diagnosis)
9
+ service.data.store(:diagnosis, service.data.fetch(:diagnosis) + [diagnosis])
14
10
  end
11
+ end
15
12
 
16
- class Mock
17
- def diagnosis(diagnosis)
18
- #self.data[:diagnosis] << rand(2) == 0 ? "sick" : "healthy"
19
- self.data.store(:diagnosis, self.data.fetch(:diagnosis) + [diagnosis])
20
- end
13
+ class Treat < Sample::Request
14
+ def real(treatment)
15
+ end
21
16
 
22
- def treat(treatment)
23
- self.data[:treatments] += [treatment]
24
- end
17
+ def mock(treatment)
18
+ service.data[:treatments] += [treatment]
25
19
  end
26
20
  end
27
21
 
28
22
  shared_examples "mock_data#backend" do |backend, options|
29
23
  it "should store mock data" do
30
- Patient.mock!
31
- Patient::Mock.store_in(backend, options)
32
- Patient.reset!
24
+ Sample.mock!
25
+ Sample::Mock.store_in(backend, options)
26
+ Sample.reset!
33
27
 
34
- p = Patient.new
28
+ p = Sample.new
35
29
  p.diagnosis("sick")
36
30
  expect(p.data[:diagnosis]).to eq(["sick"])
37
31
 
@@ -42,7 +36,7 @@ describe 'mock data' do
42
36
  p.treat("healthy")
43
37
  expect(p.data[:treatments]).to eq(["healthy"])
44
38
 
45
- Patient.reset!
39
+ Sample.reset!
46
40
 
47
41
  expect(p.data[:treatments]).to eq([])
48
42
  end
@@ -2,7 +2,7 @@ require 'spec_helper'
2
2
 
3
3
  describe "Cistern::Model" do
4
4
  describe "#update" do
5
- class UpdateSpec < Cistern::Model
5
+ class UpdateSpec < Sample::Model
6
6
  identity :id
7
7
  attribute :name
8
8
  attribute :properties
@@ -21,7 +21,7 @@ describe "Cistern::Model" do
21
21
  end
22
22
 
23
23
  it "should duplicate a model" do
24
- class DupSpec < Cistern::Model
24
+ class DupSpec < Sample::Model
25
25
  identity :id
26
26
  attribute :name
27
27
  attribute :properties
@@ -38,7 +38,7 @@ describe "Cistern::Model" do
38
38
  end
39
39
 
40
40
  context "attribute parsing" do
41
- class TypeSpec < Cistern::Model
41
+ class TypeSpec < Sample::Model
42
42
  identity :id
43
43
  attribute :name, type: :string
44
44
  attribute :created_at, type: :time
@@ -155,17 +155,17 @@ describe "Cistern::Model" do
155
155
 
156
156
  describe "#requires" do
157
157
  it "should raise if attribute not provided" do
158
- expect { TypeSpec.new({"connection" => "fake", "something" => {"id" => "12"}}).save }.to raise_exception(ArgumentError)
158
+ expect { TypeSpec.new({"service" => "fake", "something" => {"id" => "12"}}).save }.to raise_exception(ArgumentError)
159
159
  end
160
160
 
161
161
  it "should raise if attribute is provided and is nil" do
162
- expect { TypeSpec.new({"connection" => "fake", "custom" => nil}).save }.to raise_exception(ArgumentError)
162
+ expect { TypeSpec.new({"service" => "fake", "custom" => nil}).save }.to raise_exception(ArgumentError)
163
163
  end
164
164
  end
165
165
  end
166
166
 
167
167
  context "attribute coverage info collecting", :coverage do
168
- class CoverageSpec < Cistern::Model
168
+ class CoverageSpec < Sample::Model
169
169
  identity :id
170
170
 
171
171
  attribute :used, type: :string
@@ -1,29 +1,37 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe Cistern do
3
+ describe "Cistern::Request" do
4
4
  class SampleService < Cistern::Service
5
+ recognizes :key
6
+
5
7
  class Real
8
+ attr_reader :service_args
9
+
10
+ def initialize(*args)
11
+ @service_args = args
12
+ end
6
13
  end
7
14
  end
8
15
 
9
- class SampleService::GetSample < Cistern::Request
10
- service SampleService
11
-
16
+ # @todo Sample::Service.request
17
+ class ListSamples < SampleService::Request
18
+ # @todo name
19
+ # name :list_all_samples
12
20
  def real(*args)
13
- args
21
+ service.service_args + args + ["real"]
14
22
  end
15
- end
16
23
 
17
- class ShowSamples < Cistern::Request
18
- service SampleService, method: :list_samples
19
-
20
- def real(*args)
21
- {"samples" => args}
24
+ def mock(*args)
25
+ args + ["mock"]
22
26
  end
23
27
  end
24
28
 
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"])
29
+ it "should execute a new-style request" do
30
+ expect(SampleService.new.list_samples("sample1")).to eq([{}, "sample1", "real"])
31
+ expect(SampleService::Real.new.list_samples("sample2")).to eq(["sample2", "real"])
32
+ expect(SampleService::Mock.new.list_samples("sample3")).to eq(["sample3", "mock"])
33
+
34
+ # service access
35
+ expect(SampleService.new(:key => "value").list_samples("stat")).to eq([{:key => "value"}, "stat", "real"])
28
36
  end
29
37
  end
File without changes
@@ -6,8 +6,8 @@ describe "Cistern::Singular" do
6
6
  attribute :count, type: :number
7
7
 
8
8
  def fetch_attributes
9
- #test that initialize waits for connection to be defined
10
- raise "missing connection" unless connection
9
+ #test that initialize waits for service to be defined
10
+ raise "missing service" unless service
11
11
 
12
12
  @counter ||= 0
13
13
  @counter += 1
@@ -16,11 +16,11 @@ describe "Cistern::Singular" do
16
16
  end
17
17
 
18
18
  it "should work" do
19
- expect(SampleSingular.new(connection: :fake).name).to eq("amazing")
19
+ expect(SampleSingular.new(service: :fake).name).to eq("amazing")
20
20
  end
21
21
 
22
22
  it "should reload" do
23
- singular = SampleSingular.new(connection: :fake)
23
+ singular = SampleSingular.new(service: :fake)
24
24
  old_count = singular.count
25
25
  expect(singular.count).to eq(old_count)
26
26
  expect(singular.reload.count).to be > old_count
@@ -4,10 +4,13 @@ if ENV["TRAVIS"]
4
4
  end
5
5
 
6
6
  require File.expand_path('../../lib/cistern', __FILE__)
7
+ Dir[File.expand_path("../{support,shared,matchers,fixtures}/*.rb", __FILE__)].each{|f| require(f)}
7
8
 
8
9
  Bundler.require(:test)
9
10
 
10
11
  RSpec.configure do |c|
12
+ c.treat_symbols_as_metadata_keys_with_true_values = true
13
+
11
14
  if Kernel.respond_to?(:caller_locations)
12
15
  require File.expand_path('../../lib/cistern/coverage', __FILE__)
13
16
  else
@@ -0,0 +1 @@
1
+ class Sample < Cistern::Service; end
@@ -1,23 +1,13 @@
1
1
  require 'spec_helper'
2
2
 
3
- class WaitForService < Cistern::Service
4
- model :wait_for_model, require: false
5
- collection :wait_for_models, require: false
6
-
7
- class Real
8
- def initialize(*args)
9
- end
10
- end
11
- end
12
-
13
- class WaitForService::WaitForModel < Cistern::Model
3
+ class WaitForModel < Sample::Model
14
4
  identity :id
15
5
 
16
6
  attribute :name
17
7
  end
18
8
 
19
- class WaitForService::WaitForModels < Cistern::Collection
20
- model WaitForService::WaitForModel
9
+ class WaitForModels < Sample::Collection
10
+ model WaitForModel
21
11
 
22
12
  def get(identity)
23
13
  self
@@ -37,17 +27,17 @@ describe 'Cistern#wait_for!' do
37
27
  end
38
28
 
39
29
  describe 'Cistern::Model#wait_for!' do
40
- let(:service) { WaitForService.new }
30
+ let(:service) { Sample.new }
41
31
  let(:model) { service.wait_for_models.new(identity: 1) }
42
32
 
43
33
  it "should raise if timeout exceeded" do
44
- expect { model.wait_for!(0, 0) { false } }.to raise_exception(WaitForService::Timeout)
34
+ expect { model.wait_for!(0, 0) { false } }.to raise_exception(Sample::Timeout)
45
35
  end
46
36
  end
47
37
 
48
38
 
49
39
  describe "WaitForModel#timeout" do
50
- let(:service) { WaitForService.new }
40
+ let(:service) { Sample.new }
51
41
  let(:model) { service.wait_for_models.new(identity: 1) }
52
42
 
53
43
  it "should use service-specific timeout in #wait_for" do
@@ -59,7 +49,7 @@ describe "WaitForModel#timeout" do
59
49
  timeout(2) do
60
50
  expect do
61
51
  model.wait_for! { sleep(0.2); elapsed += 0.2; elapsed > 0.2 }
62
- end.to raise_exception(WaitForService::Timeout)
52
+ end.to raise_exception(Sample::Timeout)
63
53
  end
64
54
  end
65
55
 
@@ -72,7 +62,7 @@ describe "WaitForModel#timeout" do
72
62
  timeout(2) do
73
63
  expect do
74
64
  model.wait_for!(0.1) { sleep(0.2); elapsed += 0.2; elapsed > 0.2 }
75
- end.to raise_exception(WaitForService::Timeout)
65
+ end.to raise_exception(Sample::Timeout)
76
66
  end
77
67
  end
78
68
  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: 0.12.3
4
+ version: 1.0.0.pre
5
5
  platform: ruby
6
6
  authors:
7
7
  - Josh Lane
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-05-30 00:00:00.000000000 Z
11
+ date: 2014-10-21 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: API client framework extracted from Fog
14
14
  email:
@@ -17,7 +17,6 @@ executables: []
17
17
  extensions: []
18
18
  extra_rdoc_files: []
19
19
  files:
20
- - ".gemrelease"
21
20
  - ".gitignore"
22
21
  - ".travis.yml"
23
22
  - Gemfile
@@ -36,7 +35,6 @@ files:
36
35
  - lib/cistern/data/redis.rb
37
36
  - lib/cistern/formatter.rb
38
37
  - lib/cistern/formatter/awesome_print.rb
39
- - lib/cistern/formatter/default.rb
40
38
  - lib/cistern/formatter/formatador.rb
41
39
  - lib/cistern/hash.rb
42
40
  - lib/cistern/mock.rb
@@ -55,8 +53,10 @@ files:
55
53
  - spec/mock_data_spec.rb
56
54
  - spec/model_spec.rb
57
55
  - spec/request_spec.rb
56
+ - spec/service_spec.rb
58
57
  - spec/singular_spec.rb
59
58
  - spec/spec_helper.rb
59
+ - spec/support/service.rb
60
60
  - spec/wait_for_spec.rb
61
61
  homepage: http://joshualane.com/cistern
62
62
  licenses:
@@ -73,12 +73,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
73
73
  version: '0'
74
74
  required_rubygems_version: !ruby/object:Gem::Requirement
75
75
  requirements:
76
- - - ">="
76
+ - - ">"
77
77
  - !ruby/object:Gem::Version
78
- version: '0'
78
+ version: 1.3.1
79
79
  requirements: []
80
80
  rubyforge_project:
81
- rubygems_version: 2.6.12
81
+ rubygems_version: 2.2.2
82
82
  signing_key:
83
83
  specification_version: 4
84
84
  summary: API client framework
@@ -90,6 +90,9 @@ test_files:
90
90
  - spec/mock_data_spec.rb
91
91
  - spec/model_spec.rb
92
92
  - spec/request_spec.rb
93
+ - spec/service_spec.rb
93
94
  - spec/singular_spec.rb
94
95
  - spec/spec_helper.rb
96
+ - spec/support/service.rb
95
97
  - spec/wait_for_spec.rb
98
+ has_rdoc:
@@ -1,3 +0,0 @@
1
- ---
2
- bump:
3
- tag: true
@@ -1,22 +0,0 @@
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