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 CHANGED
@@ -1,3 +1,7 @@
1
+ ### 0.1.2 / 2012-02-17
2
+
3
+ * bugfix - check ReplyCode in login, retry on errors
4
+
1
5
  ### 0.1.1 / 2012-01-11
2
6
 
3
7
  * bugfix - prevent infinite loop in login
data/lib/rets.rb CHANGED
@@ -8,7 +8,7 @@ require 'net/http/persistent'
8
8
  require 'nokogiri'
9
9
 
10
10
  module Rets
11
- VERSION = '0.1.1'
11
+ VERSION = '0.1.2'
12
12
 
13
13
  AuthorizationFailure = Class.new(ArgumentError)
14
14
  InvalidRequest = Class.new(ArgumentError)
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 find_every(opts.merge(:limit => 1)).first
63
- when :all then find_every(opts)
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
- begin
289
- if !response.body.empty?
290
- xml = Nokogiri::XML.parse(response.body, nil, nil, Nokogiri::XML::ParseOptions::STRICT)
314
+ check_errors(response)
315
+ else
316
+ raise UnknownResponse, "Unable to handle response #{response.class}"
317
+ end
291
318
 
292
- reply_text = xml.xpath("/RETS").attr("ReplyText").value
293
- reply_code = xml.xpath("/RETS").attr("ReplyCode").value.to_i
319
+ return response
320
+ end
294
321
 
295
- if reply_code.nonzero?
296
- raise InvalidRequest, "Got error code #{reply_code} (#{reply_text})."
297
- end
298
- end
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
- rescue Nokogiri::XML::SyntaxError => e
301
- logger.debug "Not xml"
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
- else
306
- raise UnknownResponse, "Unable to handle response #{response.class}"
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: 25
4
+ hash: 31
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 1
9
- - 1
10
- version: 0.1.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-01-11 00:00:00 Z
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: 27
91
+ hash: 25
92
92
  segments:
93
93
  - 2
94
- - 12
95
- version: "2.12"
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.10
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