active_rest_client 0.9.58

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.
Files changed (48) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.rspec +2 -0
  4. data/.simplecov +4 -0
  5. data/Gemfile +4 -0
  6. data/Guardfile +9 -0
  7. data/LICENSE.txt +22 -0
  8. data/README.md +585 -0
  9. data/Rakefile +3 -0
  10. data/active_rest_client.gemspec +34 -0
  11. data/lib/active_rest_client.rb +23 -0
  12. data/lib/active_rest_client/base.rb +128 -0
  13. data/lib/active_rest_client/caching.rb +84 -0
  14. data/lib/active_rest_client/configuration.rb +69 -0
  15. data/lib/active_rest_client/connection.rb +76 -0
  16. data/lib/active_rest_client/connection_manager.rb +21 -0
  17. data/lib/active_rest_client/headers_list.rb +47 -0
  18. data/lib/active_rest_client/instrumentation.rb +62 -0
  19. data/lib/active_rest_client/lazy_association_loader.rb +95 -0
  20. data/lib/active_rest_client/lazy_loader.rb +23 -0
  21. data/lib/active_rest_client/logger.rb +67 -0
  22. data/lib/active_rest_client/mapping.rb +65 -0
  23. data/lib/active_rest_client/proxy_base.rb +143 -0
  24. data/lib/active_rest_client/recording.rb +24 -0
  25. data/lib/active_rest_client/request.rb +412 -0
  26. data/lib/active_rest_client/request_filtering.rb +52 -0
  27. data/lib/active_rest_client/result_iterator.rb +66 -0
  28. data/lib/active_rest_client/validation.rb +60 -0
  29. data/lib/active_rest_client/version.rb +3 -0
  30. data/spec/lib/base_spec.rb +245 -0
  31. data/spec/lib/caching_spec.rb +179 -0
  32. data/spec/lib/configuration_spec.rb +105 -0
  33. data/spec/lib/connection_manager_spec.rb +36 -0
  34. data/spec/lib/connection_spec.rb +73 -0
  35. data/spec/lib/headers_list_spec.rb +61 -0
  36. data/spec/lib/instrumentation_spec.rb +59 -0
  37. data/spec/lib/lazy_association_loader_spec.rb +118 -0
  38. data/spec/lib/lazy_loader_spec.rb +25 -0
  39. data/spec/lib/logger_spec.rb +63 -0
  40. data/spec/lib/mapping_spec.rb +48 -0
  41. data/spec/lib/proxy_spec.rb +154 -0
  42. data/spec/lib/recording_spec.rb +34 -0
  43. data/spec/lib/request_filtering_spec.rb +72 -0
  44. data/spec/lib/request_spec.rb +471 -0
  45. data/spec/lib/result_iterator_spec.rb +104 -0
  46. data/spec/lib/validation_spec.rb +113 -0
  47. data/spec/spec_helper.rb +22 -0
  48. metadata +265 -0
@@ -0,0 +1,66 @@
1
+ module ActiveRestClient
2
+ class ResultIterator
3
+ include Enumerable
4
+
5
+ attr_accessor :_status
6
+ attr_reader :items
7
+
8
+ def initialize(status = nil)
9
+ @_status = status
10
+ @items = []
11
+ end
12
+
13
+ def <<(item)
14
+ @items << item
15
+ end
16
+
17
+ def size
18
+ @items.size
19
+ end
20
+
21
+ def index(value)
22
+ @items.index(value)
23
+ end
24
+
25
+ def empty?
26
+ size == 0
27
+ end
28
+
29
+ def each
30
+ @items.each do |el|
31
+ yield el
32
+ end
33
+ end
34
+
35
+ def last
36
+ @items.last
37
+ end
38
+
39
+ def [](key)
40
+ @items[key]
41
+ end
42
+
43
+ def shuffle
44
+ @items = @items.shuffle
45
+ self
46
+ end
47
+
48
+ def parallelise(method=nil)
49
+ collected_responses = []
50
+ threads = []
51
+ @items.each do |item|
52
+ threads << Thread.new do
53
+ ret = item.send(method) if method
54
+ ret = yield(item) if block_given?
55
+ Thread.current[:response] = ret
56
+ end
57
+ end
58
+ threads.each do |t|
59
+ t.join
60
+ collected_responses << t[:response]
61
+ end
62
+ collected_responses
63
+ end
64
+
65
+ end
66
+ end
@@ -0,0 +1,60 @@
1
+ module ActiveRestClient
2
+ module Validation
3
+ module ClassMethods
4
+ def validates(field_name, options={}, &block)
5
+ @_validations ||= []
6
+ @_validations << {field_name:field_name, options:options, block:block}
7
+ end
8
+
9
+ def _validations
10
+ @_validations ||= []
11
+ @_validations
12
+ end
13
+ end
14
+
15
+ def self.included(base)
16
+ base.extend(ClassMethods)
17
+ end
18
+
19
+ def valid?
20
+ @errors = Hash.new {|h,k| h[k] = []}
21
+ self.class._validations.each do |validation|
22
+ value = self.send(validation[:field_name])
23
+ validation[:options].each do |type, options|
24
+ if type == :presence
25
+ if value.nil?
26
+ @errors[validation[:field_name]] << "must be present"
27
+ end
28
+ elsif type == :length
29
+ if options[:within]
30
+ @errors[validation[:field_name]] << "must be within range #{options[:within]}" unless options[:within].include?(value.to_s.length )
31
+ end
32
+ if options[:minimum]
33
+ @errors[validation[:field_name]] << "must be at least #{options[:minimum]} characters long" unless value.to_s.length >= options[:minimum]
34
+ end
35
+ if options[:maximum]
36
+ @errors[validation[:field_name]] << "must be no more than #{options[:minimum]} characters long" unless value.to_s.length <= options[:maximum]
37
+ end
38
+ elsif type == :numericality
39
+ numeric = (true if Float(value) rescue false)
40
+ @errors[validation[:field_name]] << "must be numeric" unless numeric
41
+ elsif type == :minimum && !value.nil?
42
+ @errors[validation[:field_name]] << "must be at least #{options}" unless value.to_f >= options.to_f
43
+ elsif type == :maximum && !value.nil?
44
+ @errors[validation[:field_name]] << "must be no more than #{options}" unless value.to_f <= options.to_f
45
+ end
46
+ end
47
+ if validation[:block]
48
+ validation[:block].call(self, validation[:field_name], value)
49
+ end
50
+ end
51
+ @errors.empty?
52
+ end
53
+
54
+ def errors
55
+ @errors ||= Hash.new {|h,k| h[k] = []}
56
+ @errors
57
+ end
58
+ end
59
+
60
+ end
@@ -0,0 +1,3 @@
1
+ module ActiveRestClient
2
+ VERSION = "0.9.58"
3
+ end
@@ -0,0 +1,245 @@
1
+ require 'spec_helper'
2
+
3
+ class EmptyExample < ActiveRestClient::Base
4
+ whiny_missing true
5
+ end
6
+
7
+ class TranslatorExample
8
+ def self.all(object)
9
+ ret = {}
10
+ ret["first_name"] = object["name"]
11
+ ret
12
+ end
13
+ end
14
+
15
+ class AlteringClientExample < ActiveRestClient::Base
16
+ translator TranslatorExample
17
+ base_url "http://www.example.com"
18
+
19
+ get :all, "/all", fake:"{\"name\":\"Billy\"}"
20
+ get :list, "/list", fake:"{\"name\":\"Billy\", \"country\":\"United Kingdom\"}"
21
+ get :iterate, "/iterate", fake:"{\"name\":\"Billy\", \"country\":\"United Kingdom\"}"
22
+ get :find, "/find/:id"
23
+ end
24
+
25
+ class RecordResponseExample < ActiveRestClient::Base
26
+ base_url "http://www.example.com"
27
+
28
+ record_response do |url, response|
29
+ raise Exception.new("#{url}|#{response.body}")
30
+ end
31
+
32
+ get :all, "/all"
33
+ end
34
+
35
+ describe ActiveRestClient::Base do
36
+ it 'should instantiate a new descendant' do
37
+ expect{EmptyExample.new}.to_not raise_error(Exception)
38
+ end
39
+
40
+ it "should not instantiate a new base class" do
41
+ expect{ActiveRestClient::Base.new}.to raise_error(Exception)
42
+ end
43
+
44
+ it "should save attributes passed in constructor" do
45
+ client = EmptyExample.new(:test => "Something")
46
+ expect(client._attributes[:test]).to be_a(String)
47
+ end
48
+
49
+ it "should allow attribute reading using missing method names" do
50
+ client = EmptyExample.new(:test => "Something")
51
+ expect(client.test).to eq("Something")
52
+ end
53
+
54
+ it "should allow attribute reading using [] array notation" do
55
+ client = EmptyExample.new(:test => "Something")
56
+ expect(client["test"]).to eq("Something")
57
+ end
58
+
59
+ it "allows iteration over attributes using each" do
60
+ client = AlteringClientExample.iterate
61
+ expect(client).to be_respond_to(:each)
62
+ keys = []
63
+ values = []
64
+ client.each do |key, value|
65
+ keys << key ; values << value
66
+ end
67
+ expect(keys).to eq(%i{name country})
68
+ expect(values).to eq(["Billy", "United Kingdom"])
69
+ end
70
+
71
+ it "should automatically parse ISO 8601 format dates" do
72
+ t = Time.now
73
+ client = EmptyExample.new(:test => t.iso8601)
74
+ expect(client["test"]).to be_an_instance_of(DateTime)
75
+ expect(client["test"].to_s).to eq(t.to_datetime.to_s)
76
+ end
77
+
78
+ it "should store attributes set using missing method names and mark them as dirty" do
79
+ client = EmptyExample.new()
80
+ client.test = "Something"
81
+ expect(client.test.to_s).to eq("Something")
82
+ expect(client).to be_dirty
83
+ end
84
+
85
+ it "should store attribute set using []= array notation and mark them as dirty" do
86
+ client = EmptyExample.new()
87
+ client["test"] = "Something"
88
+ expect(client["test"].to_s).to eq("Something")
89
+ expect(client).to be_dirty
90
+ end
91
+
92
+ it "should overwrite attributes already set and mark them as dirty" do
93
+ client = EmptyExample.new(:hello => "World")
94
+ client._clean!
95
+ expect(client).to_not be_dirty
96
+
97
+ client.hello = "Everybody"
98
+ expect(client).to be_dirty
99
+ end
100
+
101
+ it 'should respond_to? attributes defined in the response' do
102
+ client = EmptyExample.new(:hello => "World")
103
+ client.respond_to?(:hello).should be_true
104
+ client.respond_to?(:world).should be_false
105
+ end
106
+
107
+ it "should save the base URL for the API server" do
108
+ class BaseExample < ActiveRestClient::Base
109
+ base_url "https://www.example.com/api/v1"
110
+ end
111
+ expect(BaseExample.base_url).to eq("https://www.example.com/api/v1")
112
+ end
113
+
114
+ it "should allow changing the base_url while running" do
115
+ class OutsideBaseExample < ActiveRestClient::Base ; end
116
+
117
+ ActiveRestClient::Base.base_url = "https://www.example.com/api/v1"
118
+ expect(OutsideBaseExample.base_url).to eq("https://www.example.com/api/v1")
119
+
120
+ ActiveRestClient::Base.base_url = "https://www.example.com/api/v2"
121
+ expect(OutsideBaseExample.base_url).to eq("https://www.example.com/api/v2")
122
+ end
123
+
124
+ it "should include the Mapping module" do
125
+ expect(EmptyExample).to respond_to(:_calls)
126
+ expect(EmptyExample).to_not respond_to(:_non_existant)
127
+ end
128
+
129
+ it "should be able to easily clean all attributes" do
130
+ client = EmptyExample.new(hello:"World", goodbye:"Everyone")
131
+ expect(client).to be_dirty
132
+ client._clean!
133
+ expect(client).to_not be_dirty
134
+ end
135
+
136
+ it "should not overly pollute the instance method namespace to reduce chances of clashing (<10 instance methods)" do
137
+ instance_methods = EmptyExample.instance_methods - Object.methods
138
+ instance_methods = instance_methods - instance_methods.grep(/^_/)
139
+ expect(instance_methods.size).to be < 10
140
+ end
141
+
142
+ it "should raise an exception for missing attributes if whiny_missing is enabled" do
143
+ expect{EmptyExample.new.first_name}.to raise_error(ActiveRestClient::NoAttributeException)
144
+ end
145
+
146
+ it "should be able to lazy instantiate an object from a prefixed lazy_ method call" do
147
+ ActiveRestClient::Connection.any_instance.should_receive(:get).with('/find/1', anything).and_return(OpenStruct.new(status:200, headers:{}, body:"{\"first_name\":\"Billy\"}"))
148
+ example = AlteringClientExample.lazy_find(1)
149
+ expect(example).to be_an_instance_of(ActiveRestClient::LazyLoader)
150
+ expect(example.first_name).to eq("Billy")
151
+ end
152
+
153
+ it "should be able to lazy instantiate an object from a prefixed lazy_ method call from an instance" do
154
+ ActiveRestClient::Connection.any_instance.should_receive(:get).with('/find/1', anything).and_return(OpenStruct.new(status:200, headers:{}, body:"{\"first_name\":\"Billy\"}"))
155
+ example = AlteringClientExample.new.lazy_find(1)
156
+ expect(example).to be_an_instance_of(ActiveRestClient::LazyLoader)
157
+ expect(example.first_name).to eq("Billy")
158
+ end
159
+
160
+ context "accepts a Translator to reformat JSON" do
161
+ it "should log a deprecation warning when using a translator" do
162
+ ActiveRestClient::Logger.should_receive(:warn) do |message|
163
+ expect(message).to start_with("DEPRECATION")
164
+ end
165
+ Proc.new do
166
+ class DummyExample < ActiveRestClient::Base
167
+ translator TranslatorExample
168
+ end
169
+ end.call
170
+ end
171
+
172
+ it "should call Translator#method when calling the mapped method if it responds to it" do
173
+ TranslatorExample.should_receive(:all).with(an_instance_of(Hash)).and_return({})
174
+ AlteringClientExample.all
175
+ end
176
+
177
+ it "should not raise errors when calling Translator#method if it does not respond to it" do
178
+ expect {AlteringClientExample.list}.to_not raise_error
179
+ end
180
+
181
+ it "should translate JSON returned through the Translator" do
182
+ ret = AlteringClientExample.all
183
+ expect(ret.first_name).to eq("Billy")
184
+ expect(ret.name).to be_nil
185
+ end
186
+
187
+ it "should return original JSON for items that aren't handled by the Translator" do
188
+ ret = AlteringClientExample.list
189
+ expect(ret.name).to eq("Billy")
190
+ expect(ret.first_name).to be_nil
191
+ end
192
+ end
193
+
194
+ context "directly call a URL, rather than via a mapped method" do
195
+ it "should be able to directly call a URL" do
196
+ ActiveRestClient::Request.any_instance.should_receive(:do_request).with(any_args).and_return(OpenStruct.new(status:200, headers:{}, body:"{\"first_name\":\"Billy\"}"))
197
+ EmptyExample._request("http://api.example.com/")
198
+ end
199
+
200
+ it "runs filters as usual" do
201
+ ActiveRestClient::Request.any_instance.should_receive(:do_request).with(any_args).and_return(OpenStruct.new(status:200, headers:{}, body:"{\"first_name\":\"Billy\"}"))
202
+ EmptyExample.should_receive(:_filter_request).with(any_args)
203
+ EmptyExample._request("http://api.example.com/")
204
+ end
205
+
206
+ it "should make an HTTP request" do
207
+ ActiveRestClient::Connection.any_instance.should_receive(:get).with(any_args).and_return(OpenStruct.new(status:200, headers:{}, body:"{\"first_name\":\"Billy\"}"))
208
+ EmptyExample._request("http://api.example.com/")
209
+ end
210
+
211
+ it "should map the response from the directly called URL in the normal way" do
212
+ ActiveRestClient::Request.any_instance.should_receive(:do_request).with(any_args).and_return(OpenStruct.new(status:200, headers:{}, body:"{\"first_name\":\"Billy\"}"))
213
+ example = EmptyExample._request("http://api.example.com/")
214
+ expect(example.first_name).to eq("Billy")
215
+ end
216
+
217
+ it "should be able to lazy load a direct URL request" do
218
+ ActiveRestClient::Request.any_instance.should_receive(:do_request).with(any_args).and_return(OpenStruct.new(status:200, headers:{}, body:"{\"first_name\":\"Billy\"}"))
219
+ example = EmptyExample._lazy_request("http://api.example.com/")
220
+ expect(example).to be_an_instance_of(ActiveRestClient::LazyLoader)
221
+ expect(example.first_name).to eq("Billy")
222
+ end
223
+
224
+ it "should be able to specify a method and parameters for the call" do
225
+ ActiveRestClient::Connection.any_instance.should_receive(:post).with(any_args).and_return(OpenStruct.new(status:200, headers:{}, body:"{\"first_name\":\"Billy\"}"))
226
+ EmptyExample._request("http://api.example.com/", :post, {id:1234})
227
+ end
228
+
229
+ it "should be able to use mapped methods to create a request to pass in to _lazy_request" do
230
+ ActiveRestClient::Connection.any_instance.should_receive(:get).with('/find/1', anything).and_return(OpenStruct.new(status:200, headers:{}, body:"{\"first_name\":\"Billy\"}"))
231
+ request = AlteringClientExample._request_for(:find, :id => 1)
232
+ example = AlteringClientExample._lazy_request(request)
233
+ expect(example.first_name).to eq("Billy")
234
+ end
235
+ end
236
+
237
+ context "Recording a response" do
238
+ it "calls back to the record_response callback with the url and response body" do
239
+ ActiveRestClient::Connection.any_instance.should_receive(:get).with(any_args).and_return(OpenStruct.new(status:200, headers:{}, body:"Hello world"))
240
+ expect{RecordResponseExample.all}.to raise_error(Exception, "/all|Hello world")
241
+
242
+ end
243
+ end
244
+
245
+ end
@@ -0,0 +1,179 @@
1
+ require 'spec_helper'
2
+
3
+ describe ActiveRestClient::Caching do
4
+ before :each do
5
+ ActiveRestClient::Base._reset_caching!
6
+ end
7
+
8
+ context "Configuration of caching" do
9
+ it "should not have caching enabled by default" do
10
+ class CachingExample1
11
+ include ActiveRestClient::Caching
12
+ end
13
+ expect(CachingExample1.perform_caching).to be_false
14
+ end
15
+
16
+ it "should be able to have caching enabled without affecting ActiveRestClient::Base" do
17
+ class CachingExample2
18
+ include ActiveRestClient::Caching
19
+ end
20
+ CachingExample2.perform_caching true
21
+ expect(CachingExample2.perform_caching).to be_true
22
+ expect(ActiveRestClient::Base.perform_caching).to be_false
23
+ end
24
+
25
+ it "should be possible to enable caching for all objects" do
26
+ class CachingExample3 < ActiveRestClient::Base ; end
27
+ ActiveRestClient::Base._reset_caching!
28
+
29
+ expect(ActiveRestClient::Base.perform_caching).to be_false
30
+
31
+ ActiveRestClient::Base.perform_caching = true
32
+ expect(ActiveRestClient::Base.perform_caching).to be_true
33
+ expect(EmptyExample.perform_caching).to be_true
34
+
35
+ ActiveRestClient::Base._reset_caching!
36
+ end
37
+
38
+ it "should use Rails.cache if available" do
39
+ begin
40
+ class Rails
41
+ def self.cache
42
+ true
43
+ end
44
+ end
45
+ expect(ActiveRestClient::Base.cache_store).to eq(true)
46
+ ensure
47
+ Object.send(:remove_const, :Rails) if defined?(Rails)
48
+ end
49
+
50
+ end
51
+
52
+ it "should use a custom cache store if a valid one is manually set" do
53
+ class CachingExampleCacheStore1
54
+ def read(key) ; end
55
+ def write(key, value, options={}) ; end
56
+ def fetch(key, &block) ; end
57
+ end
58
+ cache_store = CachingExampleCacheStore1.new
59
+ ActiveRestClient::Base.cache_store = cache_store
60
+ expect(ActiveRestClient::Base.cache_store).to eq(cache_store)
61
+ end
62
+
63
+ it "should error if you try to use a custom cache store that doesn't match the required interface" do
64
+ class CachingExampleCacheStore2
65
+ def write(key, value, options={}) ; end
66
+ def fetch(key, &block) ; end
67
+ end
68
+ class CachingExampleCacheStore3
69
+ def read(key) ; end
70
+ def fetch(key, &block) ; end
71
+ end
72
+ class CachingExampleCacheStore4
73
+ def read(key) ; end
74
+ def write(key, value, options={}) ; end
75
+ end
76
+
77
+ expect{ ActiveRestClient::Base.cache_store = CachingExampleCacheStore2.new }.to raise_error
78
+ expect{ ActiveRestClient::Base.cache_store = CachingExampleCacheStore3.new }.to raise_error
79
+ expect{ ActiveRestClient::Base.cache_store = CachingExampleCacheStore4.new }.to raise_error
80
+ end
81
+ end
82
+
83
+ context "Reading/writing to the cache" do
84
+ before :each do
85
+ Object.send(:remove_const, :CachingExampleCacheStore5) if defined?(CachingExampleCacheStore5)
86
+ class CachingExampleCacheStore5
87
+ def read(key) ; end
88
+ def write(key, value, options={}) ; end
89
+ def fetch(key, &block) ; end
90
+ end
91
+
92
+ class Person < ActiveRestClient::Base
93
+ perform_caching true
94
+ base_url "http://www.example.com"
95
+ get :all, "/"
96
+ end
97
+
98
+ Person.cache_store = CachingExampleCacheStore5.new
99
+
100
+ @etag = "6527914a91e0c5769f6de281f25bd891"
101
+ @cached_object = Person.new(first_name:"Johnny")
102
+ end
103
+
104
+ it "should read from the cache store, to check for an etag" do
105
+ cached_response = ActiveRestClient::CachedResponse.new(
106
+ status:200,
107
+ result:@cached_object,
108
+ etag:@etag)
109
+ CachingExampleCacheStore5.any_instance.should_receive(:read).once.with("Person:/").and_return(cached_response)
110
+ ActiveRestClient::Connection.any_instance.should_receive(:get).with("/", hash_including("If-None-Match" => @etag)).and_return(OpenStruct.new(status:304, headers:{}))
111
+ ret = Person.all
112
+ expect(ret.first_name).to eq("Johnny")
113
+ end
114
+
115
+ it "should read from the cache store, and not call the server if there's a hard expiry" do
116
+ cached_response = ActiveRestClient::CachedResponse.new(
117
+ status:200,
118
+ result:@cached_object,
119
+ expires:Time.now + 30)
120
+ CachingExampleCacheStore5.any_instance.should_receive(:read).once.with("Person:/").and_return(cached_response)
121
+ ActiveRestClient::Connection.any_instance.should_not_receive(:get)
122
+ ret = Person.all
123
+ expect(ret.first_name).to eq("Johnny")
124
+ end
125
+
126
+ it "should read from the cache store and restore to the same object" do
127
+ cached_response = ActiveRestClient::CachedResponse.new(
128
+ status:200,
129
+ result:@cached_object,
130
+ expires:Time.now + 30)
131
+ CachingExampleCacheStore5.any_instance.should_receive(:read).once.with("Person:/").and_return(cached_response)
132
+ ActiveRestClient::Connection.any_instance.should_not_receive(:get)
133
+ p = Person.new(first_name:"Billy")
134
+ ret = p.all({})
135
+ expect(ret.first_name).to eq("Johnny")
136
+ end
137
+
138
+ it "should restore a result iterator from the cache store, if there's a hard expiry" do
139
+ class CachingExample3 < ActiveRestClient::Base ; end
140
+ object = ActiveRestClient::ResultIterator.new(200)
141
+ object << CachingExample3.new(first_name:"Johnny")
142
+ object << CachingExample3.new(first_name:"Billy")
143
+ etag = "6527914a91e0c5769f6de281f25bd891"
144
+ cached_response = ActiveRestClient::CachedResponse.new(
145
+ status:200,
146
+ result:object,
147
+ etag:@etag,
148
+ expires:Time.now + 30)
149
+ CachingExampleCacheStore5.any_instance.should_receive(:read).once.with("Person:/").and_return(cached_response)
150
+ ActiveRestClient::Connection.any_instance.should_not_receive(:get)
151
+ ret = Person.all
152
+ expect(ret.first.first_name).to eq("Johnny")
153
+ expect(ret._status).to eq(200)
154
+ end
155
+
156
+ it "should not write the response to the cache unless if has caching headers" do
157
+ CachingExampleCacheStore5.any_instance.should_receive(:read).once.with("Person:/").and_return(nil)
158
+ CachingExampleCacheStore5.any_instance.should_not_receive(:write)
159
+ ActiveRestClient::Connection.any_instance.should_receive(:get).with("/", an_instance_of(Hash)).and_return(OpenStruct.new(status:200, body:"{\"result\":true}", headers:{}))
160
+ ret = Person.all
161
+ end
162
+
163
+ it "should write the response to the cache if there's an etag" do
164
+ CachingExampleCacheStore5.any_instance.should_receive(:read).once.with("Person:/").and_return(nil)
165
+ CachingExampleCacheStore5.any_instance.should_receive(:write).once.with("Person:/", an_instance_of(ActiveRestClient::CachedResponse), {})
166
+ ActiveRestClient::Connection.any_instance.should_receive(:get).with("/", an_instance_of(Hash)).and_return(OpenStruct.new(status:200, body:"{\"result\":true}", headers:{etag:"1234567890"}))
167
+ ret = Person.all
168
+ end
169
+
170
+ it "should write the response to the cache if there's a hard expiry" do
171
+ CachingExampleCacheStore5.any_instance.should_receive(:read).once.with("Person:/").and_return(nil)
172
+ CachingExampleCacheStore5.any_instance.should_receive(:write).once.with("Person:/", an_instance_of(ActiveRestClient::CachedResponse), an_instance_of(Hash))
173
+ ActiveRestClient::Connection.any_instance.should_receive(:get).with("/", an_instance_of(Hash)).and_return(OpenStruct.new(status:200, body:"{\"result\":true}", headers:{expires:(Time.now + 30).rfc822}))
174
+ ret = Person.all
175
+ end
176
+
177
+ end
178
+
179
+ end