rets 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +4 -0
- data/lib/rets.rb +1 -1
- data/lib/rets/client.rb +52 -25
- data/test/test_client.rb +17 -0
- metadata +8 -8
data/CHANGELOG.md
CHANGED
data/lib/rets.rb
CHANGED
data/lib/rets/client.rb
CHANGED
@@ -10,22 +10,32 @@ module Rets
|
|
10
10
|
attr_writer :capabilities, :metadata
|
11
11
|
|
12
12
|
def initialize(options)
|
13
|
+
@options = options
|
14
|
+
clean_setup
|
15
|
+
end
|
16
|
+
|
17
|
+
def clean_setup
|
18
|
+
|
13
19
|
@capabilities = nil
|
14
20
|
@cookies = nil
|
15
21
|
@metadata = nil
|
22
|
+
@cached_metadata = nil
|
23
|
+
|
24
|
+
self.authorization = nil
|
25
|
+
self.capabilities = nil
|
16
26
|
|
17
|
-
uri = URI.parse(options[:login_url])
|
27
|
+
uri = URI.parse(@options[:login_url])
|
18
28
|
|
19
|
-
uri.user = options.key?(:username) ? CGI.escape(options[:username]) : nil
|
20
|
-
uri.password = options.key?(:password) ? CGI.escape(options[:password]) : nil
|
29
|
+
uri.user = @options.key?(:username) ? CGI.escape(@options[:username]) : nil
|
30
|
+
uri.password = @options.key?(:password) ? CGI.escape(@options[:password]) : nil
|
21
31
|
|
22
|
-
self.options = DEFAULT_OPTIONS.merge(options)
|
32
|
+
self.options = DEFAULT_OPTIONS.merge(@options)
|
23
33
|
self.uri = uri
|
24
34
|
|
25
|
-
self.logger = options[:logger] || FakeLogger.new
|
35
|
+
self.logger = @options[:logger] || FakeLogger.new
|
26
36
|
|
27
|
-
self.session = options[:session] if options[:session]
|
28
|
-
@cached_metadata = options[:metadata] || nil
|
37
|
+
self.session = @options[:session] if @options[:session]
|
38
|
+
@cached_metadata = @options[:metadata] || nil
|
29
39
|
end
|
30
40
|
|
31
41
|
|
@@ -59,14 +69,29 @@ module Rets
|
|
59
69
|
#
|
60
70
|
def find(quantity, opts = {})
|
61
71
|
case quantity
|
62
|
-
when :first then
|
63
|
-
when :all then
|
72
|
+
when :first then find_with_retries(opts.merge(:limit => 1)).first
|
73
|
+
when :all then find_with_retries(opts)
|
64
74
|
else raise ArgumentError, "First argument must be :first or :all"
|
65
75
|
end
|
66
76
|
end
|
67
77
|
|
68
78
|
alias search find
|
69
79
|
|
80
|
+
def find_with_retries(opts = {})
|
81
|
+
retries = 0
|
82
|
+
begin
|
83
|
+
find_every(opts)
|
84
|
+
rescue AuthorizationFailure, InvalidRequest => e
|
85
|
+
if retries < 3
|
86
|
+
retries += 1
|
87
|
+
self.logger.warn "Failed with message: #{e.message}"
|
88
|
+
self.logger.info "Retry #{retries}/3"
|
89
|
+
clean_setup
|
90
|
+
retry
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
70
95
|
def find_every(opts = {})
|
71
96
|
search_uri = capability_url("Search")
|
72
97
|
|
@@ -275,6 +300,7 @@ module Rets
|
|
275
300
|
if Net::HTTPUnauthorized === response
|
276
301
|
raise AuthorizationFailure, "Authorization failed, check credentials?"
|
277
302
|
else
|
303
|
+
check_errors(response)
|
278
304
|
self.capabilities = extract_capabilities(Nokogiri.parse(response.body))
|
279
305
|
end
|
280
306
|
end
|
@@ -285,31 +311,32 @@ module Rets
|
|
285
311
|
handle_unauthorized_response(response)
|
286
312
|
|
287
313
|
elsif Net::HTTPSuccess === response # 2xx
|
288
|
-
|
289
|
-
|
290
|
-
|
314
|
+
check_errors(response)
|
315
|
+
else
|
316
|
+
raise UnknownResponse, "Unable to handle response #{response.class}"
|
317
|
+
end
|
291
318
|
|
292
|
-
|
293
|
-
|
319
|
+
return response
|
320
|
+
end
|
294
321
|
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
322
|
+
def check_errors(response)
|
323
|
+
begin
|
324
|
+
if !response.body.empty?
|
325
|
+
xml = Nokogiri::XML.parse(response.body, nil, nil, Nokogiri::XML::ParseOptions::STRICT)
|
299
326
|
|
300
|
-
|
301
|
-
|
327
|
+
reply_text = xml.xpath("/RETS").attr("ReplyText").value
|
328
|
+
reply_code = xml.xpath("/RETS").attr("ReplyCode").value.to_i
|
302
329
|
|
330
|
+
if reply_code.nonzero?
|
331
|
+
raise InvalidRequest, "Got error code #{reply_code} (#{reply_text})."
|
332
|
+
end
|
303
333
|
end
|
304
334
|
|
305
|
-
|
306
|
-
|
335
|
+
rescue Nokogiri::XML::SyntaxError => e
|
336
|
+
logger.debug "Not xml"
|
307
337
|
end
|
308
|
-
|
309
|
-
return response
|
310
338
|
end
|
311
339
|
|
312
|
-
|
313
340
|
def handle_cookies(response)
|
314
341
|
if cookies?(response)
|
315
342
|
self.cookies = response.get_fields('set-cookie')
|
data/test/test_client.rb
CHANGED
@@ -116,6 +116,18 @@ class TestClient < Test::Unit::TestCase
|
|
116
116
|
end
|
117
117
|
end
|
118
118
|
|
119
|
+
def test_handle_unauthorize_response_handles_rets_errors
|
120
|
+
response = Net::HTTPSuccess.new("", "", "")
|
121
|
+
response.stubs(:body => RETS_ERROR)
|
122
|
+
@client.stubs(:build_auth)
|
123
|
+
@client.stubs(:extract_digest_header)
|
124
|
+
@client.stubs(:raw_request).returns(response)
|
125
|
+
|
126
|
+
assert_raise Rets::InvalidRequest do
|
127
|
+
@client.handle_unauthorized_response(response)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
119
131
|
def test_handle_response_handles_rets_valid_response
|
120
132
|
response = Net::HTTPSuccess.new("", "", "")
|
121
133
|
response.stubs(:body => RETS_REPLY)
|
@@ -420,6 +432,11 @@ DIGEST
|
|
420
432
|
end
|
421
433
|
end
|
422
434
|
|
435
|
+
def test_find_retries_on_errors
|
436
|
+
@client.stubs(:find_every).raises(Rets::AuthorizationFailure).then.raises(Rets::InvalidRequest).then.returns([])
|
437
|
+
@client.find(:all, :foo => :bar)
|
438
|
+
end
|
439
|
+
|
423
440
|
def test_find_provides_default_values
|
424
441
|
@client.expects(:build_key_values).
|
425
442
|
with("QueryType" => "DMQL2", "Format" => "COMPACT", "Query" => "x", "Foo" => "bar").
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rets
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 31
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 0.1.
|
9
|
+
- 2
|
10
|
+
version: 0.1.2
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Estately, Inc. Open Source
|
@@ -16,7 +16,7 @@ autorequire:
|
|
16
16
|
bindir: bin
|
17
17
|
cert_chain: []
|
18
18
|
|
19
|
-
date: 2012-
|
19
|
+
date: 2012-02-17 00:00:00 Z
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
22
22
|
name: net-http-persistent
|
@@ -88,11 +88,11 @@ dependencies:
|
|
88
88
|
requirements:
|
89
89
|
- - ~>
|
90
90
|
- !ruby/object:Gem::Version
|
91
|
-
hash:
|
91
|
+
hash: 25
|
92
92
|
segments:
|
93
93
|
- 2
|
94
|
-
-
|
95
|
-
version: "2.
|
94
|
+
- 13
|
95
|
+
version: "2.13"
|
96
96
|
type: :development
|
97
97
|
version_requirements: *id005
|
98
98
|
description: |-
|
@@ -163,7 +163,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
163
163
|
requirements: []
|
164
164
|
|
165
165
|
rubyforge_project: rets
|
166
|
-
rubygems_version: 1.8.
|
166
|
+
rubygems_version: 1.8.15
|
167
167
|
signing_key:
|
168
168
|
specification_version: 3
|
169
169
|
summary: A pure-ruby library for fetching data from [RETS] servers
|