rets-hack 0.11

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +142 -0
  3. data/Manifest.txt +58 -0
  4. data/README.md +129 -0
  5. data/Rakefile +28 -0
  6. data/bin/rets +202 -0
  7. data/example/connect.rb +19 -0
  8. data/example/get-photos.rb +20 -0
  9. data/example/get-property.rb +16 -0
  10. data/lib/rets/client.rb +373 -0
  11. data/lib/rets/client_progress_reporter.rb +48 -0
  12. data/lib/rets/http_client.rb +133 -0
  13. data/lib/rets/locking_http_client.rb +34 -0
  14. data/lib/rets/measuring_http_client.rb +27 -0
  15. data/lib/rets/metadata/caching.rb +59 -0
  16. data/lib/rets/metadata/containers.rb +89 -0
  17. data/lib/rets/metadata/file_cache.rb +29 -0
  18. data/lib/rets/metadata/json_serializer.rb +27 -0
  19. data/lib/rets/metadata/lookup_table.rb +65 -0
  20. data/lib/rets/metadata/lookup_type.rb +19 -0
  21. data/lib/rets/metadata/marshal_serializer.rb +27 -0
  22. data/lib/rets/metadata/multi_lookup_table.rb +70 -0
  23. data/lib/rets/metadata/null_cache.rb +24 -0
  24. data/lib/rets/metadata/resource.rb +103 -0
  25. data/lib/rets/metadata/rets_class.rb +57 -0
  26. data/lib/rets/metadata/rets_object.rb +41 -0
  27. data/lib/rets/metadata/root.rb +155 -0
  28. data/lib/rets/metadata/table.rb +33 -0
  29. data/lib/rets/metadata/table_factory.rb +19 -0
  30. data/lib/rets/metadata/yaml_serializer.rb +27 -0
  31. data/lib/rets/metadata.rb +18 -0
  32. data/lib/rets/parser/compact.rb +117 -0
  33. data/lib/rets/parser/error_checker.rb +56 -0
  34. data/lib/rets/parser/multipart.rb +39 -0
  35. data/lib/rets.rb +269 -0
  36. data/test/fixtures.rb +324 -0
  37. data/test/helper.rb +14 -0
  38. data/test/test_caching.rb +89 -0
  39. data/test/test_client.rb +307 -0
  40. data/test/test_error_checker.rb +87 -0
  41. data/test/test_file_cache.rb +42 -0
  42. data/test/test_http_client.rb +132 -0
  43. data/test/test_json_serializer.rb +26 -0
  44. data/test/test_locking_http_client.rb +29 -0
  45. data/test/test_marshal_serializer.rb +26 -0
  46. data/test/test_metadata.rb +71 -0
  47. data/test/test_metadata_class.rb +50 -0
  48. data/test/test_metadata_lookup_table.rb +21 -0
  49. data/test/test_metadata_lookup_type.rb +21 -0
  50. data/test/test_metadata_multi_lookup_table.rb +60 -0
  51. data/test/test_metadata_object.rb +33 -0
  52. data/test/test_metadata_resource.rb +148 -0
  53. data/test/test_metadata_root.rb +151 -0
  54. data/test/test_metadata_table.rb +21 -0
  55. data/test/test_metadata_table_factory.rb +24 -0
  56. data/test/test_parser_compact.rb +115 -0
  57. data/test/test_parser_multipart.rb +39 -0
  58. data/test/test_yaml_serializer.rb +26 -0
  59. data/test/vcr_cassettes/unauthorized_response.yml +262 -0
  60. metadata +227 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: aa7eec964ae1e040ba2d291f5283432661b1a08c
4
+ data.tar.gz: 597bbab53e0a16701d8b070cf193f7d4bc015053
5
+ SHA512:
6
+ metadata.gz: 4946f647c2cc1a67f644018c50918cfb6fd992ce13eda38de79db7ea5f842f7e7aa10dadb8244b7f4ef908cac4c4ebe564cad1a2191bc1819972a70e66d7278f
7
+ data.tar.gz: 994a48a22bef9a8f03a1195a685339e9d6d2a29a985172962e312d072b1487b8f37a51819afe22765f1d5fbd2627afa65f6c0a0dbe1917ce6a61302b77b17466
data/CHANGELOG.md ADDED
@@ -0,0 +1,142 @@
1
+ ### 0.11.0 / NOT RELEASED YET
2
+
3
+ * fix: fix retry logging
4
+ * feature: allow retries to be configured for all query types in client settings
5
+ * feature: allow configrable wait time between retries
6
+ * feature: detect errors as error messages in a response body delivered with HTTP 200
7
+
8
+ ### 0.10.1 / 2016-05-04
9
+
10
+ * fix: handle invalid codepoints in character references
11
+
12
+ ### 0.10.0 / 2016-02-29
13
+
14
+ * fix: ensure cookie store exists #133
15
+ * feature: make cached capabilities case insensitive #136
16
+ * feature: add specific classes for each rets error #137
17
+ * feature: whitelist RETS search options #142
18
+ * feature: simplify metadata caching #134
19
+ * feature: use a SAX parser #98
20
+ * fix: save capabilities to avoid double logins #148
21
+ * feature: login on authorization error #155
22
+ * add basic support for DataDictionary feeds #156
23
+ * fix: count always returns a number #161
24
+ * feature: make lookup tables case insensitive #163
25
+ * feature: update to httpclient 2.7 #165
26
+ * fix: getObject now works with non-multipart responses #166
27
+ * fix: getObject works with multiple ids #167
28
+ * feature: store rets object metadata #168
29
+ * feature: add a code of conduct #171
30
+
31
+ ### 0.9.0 / 2015-06-11
32
+
33
+ * feature: update to httpclient 2.6
34
+
35
+ ### 0.8.1 / 2015-06-09
36
+
37
+ * fix: actually make the httpclient version more specific this time
38
+
39
+ ### 0.8.0 / 2015-06-09
40
+
41
+ * feature: reduce memory usage on parsing metadata
42
+ * fix: correctly raise authorization error when given XHTML instead of XML
43
+ * fix: unescape HTML encoded responses
44
+ * fix: make httpclient version requirement more specific
45
+ * feature: add ability to print metadata to a file
46
+ * fix: remove Gemfile.lock from repository
47
+
48
+ ### 0.7.0 / 2015-01-16
49
+
50
+ * feature: optionally treat No Records Found as not an error
51
+ * fix: update httpclient version, patches SSL vulnerabilities
52
+ * feature: work around bogus http status codes that don't agree with XML body
53
+
54
+ ### 0.6.0 / 2014-11-26
55
+
56
+ * fix: fix spelling error that created misleading exceptions
57
+ * feature: track stats for http requests sent
58
+ * feature: raise an exception if the login action doesn't return an http 200 status
59
+ * feature: add better class description and more fields to print tree
60
+ * feature: support http proxies
61
+ * feature: customizable http timeouts
62
+ * feature: add logging http headers when in debug mode
63
+ * feature: strip invalid utf8 from responses before parsing
64
+ * fix: don't raise an exception on a 401 after logout
65
+ * fix: treat no matching records status without a count node as a zero count
66
+ * feature: add an option for loading custom ca_certs
67
+ * feature: remove invalid resource types from metadata
68
+ * feature: special case http 412
69
+ * feature: add max_retries option
70
+
71
+ ### 0.5.1 / 2013-10-30
72
+
73
+ * fix: 0.5.0 was broken, fix gem Manifest to fix gem
74
+
75
+ ### 0.5.0 / 2013-09-05
76
+
77
+ * feature: Allow client.count to get integer count
78
+ * feature: Allow for downcased capability names
79
+ * fix: Handle the rets element being empty
80
+ * feature: Instrument rets client with stats reporting
81
+ * feature: Add a locking client
82
+ * feature: Support Basic Authentication
83
+
84
+ ### 0.4.0 / 2012-08-29
85
+
86
+ * fix: update authentication header to uri matches path
87
+
88
+ ### 0.3.0 / 2012-07-31
89
+
90
+ * correctly handle digest authentication
91
+
92
+ ### 0.3.0.rc.0 / 2012-07-26
93
+
94
+ * feature: significantly better handling of authorization failures
95
+
96
+ ### 0.2.1 / 2012-04-20
97
+
98
+ * fix: better handling of malformed RETS responses
99
+
100
+ ### 0.2.0 / 2012-04-20
101
+
102
+ * feature: Ruby 1.9 compatibility!
103
+
104
+ ### 0.1.7 / 2012-04-05
105
+
106
+ * feature: key_field lookup for resources
107
+
108
+ ### 0.1.6 / 2012-04-03
109
+
110
+ * fix: user_agent authentication
111
+
112
+ ### 0.1.5 / 2012-03-17
113
+
114
+ * fix: retries raise error after too many failures
115
+ * fix: raise error for failed multipart object request
116
+ * fix: retries start with a clean slate, fixing authorization errors during retry
117
+
118
+ ### 0.1.4 / 2012-03-12
119
+
120
+ * fix: an MLS uses lower case in RETS tag
121
+
122
+ ### 0.1.3 / 2012-03-05
123
+
124
+ * fixes to support location=1 in getobject query
125
+
126
+ ### 0.1.2 / 2012-02-17
127
+
128
+ * bugfix - check ReplyCode in login, retry on errors
129
+
130
+ ### 0.1.1 / 2012-01-11
131
+
132
+ * bugfix - prevent infinite loop in login
133
+
134
+ # rets Changelog
135
+
136
+ ### 0.1.0 / 2011-06-23
137
+
138
+ * First public release!
139
+
140
+ ### 0.0.1 / 2011-03-24
141
+
142
+ * Project Created
data/Manifest.txt ADDED
@@ -0,0 +1,58 @@
1
+ CHANGELOG.md
2
+ Manifest.txt
3
+ README.md
4
+ Rakefile
5
+ bin/rets
6
+ example/connect.rb
7
+ example/get-photos.rb
8
+ example/get-property.rb
9
+ lib/rets.rb
10
+ lib/rets/client.rb
11
+ lib/rets/client_progress_reporter.rb
12
+ lib/rets/http_client.rb
13
+ lib/rets/locking_http_client.rb
14
+ lib/rets/measuring_http_client.rb
15
+ lib/rets/metadata.rb
16
+ lib/rets/metadata/caching.rb
17
+ lib/rets/metadata/containers.rb
18
+ lib/rets/metadata/file_cache.rb
19
+ lib/rets/metadata/json_serializer.rb
20
+ lib/rets/metadata/lookup_table.rb
21
+ lib/rets/metadata/lookup_type.rb
22
+ lib/rets/metadata/marshal_serializer.rb
23
+ lib/rets/metadata/multi_lookup_table.rb
24
+ lib/rets/metadata/null_cache.rb
25
+ lib/rets/metadata/resource.rb
26
+ lib/rets/metadata/rets_class.rb
27
+ lib/rets/metadata/rets_object.rb
28
+ lib/rets/metadata/root.rb
29
+ lib/rets/metadata/table.rb
30
+ lib/rets/metadata/table_factory.rb
31
+ lib/rets/metadata/yaml_serializer.rb
32
+ lib/rets/parser/compact.rb
33
+ lib/rets/parser/error_checker.rb
34
+ lib/rets/parser/multipart.rb
35
+ test/fixtures.rb
36
+ test/helper.rb
37
+ test/test_caching.rb
38
+ test/test_client.rb
39
+ test/test_error_checker.rb
40
+ test/test_file_cache.rb
41
+ test/test_http_client.rb
42
+ test/test_json_serializer.rb
43
+ test/test_locking_http_client.rb
44
+ test/test_marshal_serializer.rb
45
+ test/test_metadata.rb
46
+ test/test_metadata_class.rb
47
+ test/test_metadata_lookup_table.rb
48
+ test/test_metadata_lookup_type.rb
49
+ test/test_metadata_multi_lookup_table.rb
50
+ test/test_metadata_object.rb
51
+ test/test_metadata_resource.rb
52
+ test/test_metadata_root.rb
53
+ test/test_metadata_table.rb
54
+ test/test_metadata_table_factory.rb
55
+ test/test_parser_compact.rb
56
+ test/test_parser_multipart.rb
57
+ test/test_yaml_serializer.rb
58
+ test/vcr_cassettes/unauthorized_response.yml
data/README.md ADDED
@@ -0,0 +1,129 @@
1
+ # rets
2
+
3
+ * http://github.com/estately/rets
4
+
5
+ ## DESCRIPTION:
6
+
7
+ [![Build Status](https://secure.travis-ci.org/estately/rets.png?branch=master)](http://travis-ci.org/estately/rets)
8
+ A pure-ruby library for fetching data from [RETS] servers.
9
+
10
+ If you're looking for a slick CLI interface check out [retscli](https://github.com/summera/retscli), which is an awesome tool for exploring metadata or learning about RETS.
11
+
12
+ [RETS]: http://www.rets.org
13
+
14
+ ## REQUIREMENTS:
15
+
16
+ * [httpclient]
17
+ * [nokogiri]
18
+
19
+ [httpclient]: https://github.com/nahi/httpclient
20
+ [nokogiri]: http://nokogiri.org
21
+
22
+ ## INSTALLATION:
23
+ ```
24
+ gem install rets
25
+
26
+ # or add it to your Gemfile if using Bundler then run bundle install
27
+ gem 'rets'
28
+ ```
29
+
30
+ ## EXAMPLE USAGE:
31
+
32
+ We need work in this area! There are currently a few guideline examples in the `example` folder on connecting, fetching a property's data, and fetching a property's photos.
33
+
34
+ ## Metadata caching
35
+
36
+ Metadata, which is loaded when a client is first started, can be slow
37
+ to fetch. To avoid the cost of fetching metadata every time the
38
+ client is started, metadata can be cached.
39
+
40
+ To cache metadata, pass the :metadata_cache option to the client when
41
+ you start it. The library comes with a predefined metadata cache that
42
+ persists the metadata to a file. It is created with the path to which
43
+ the cached metadata should be written:
44
+
45
+ metadata_cache = Rets::Metadata::FileCache.new("/tmp/metadata")
46
+
47
+ When you create the RETS client, pass it the metadata cache:
48
+
49
+ client = Rets::Client.new(
50
+ ...
51
+ metadata_cache: metadata_cache
52
+ )
53
+
54
+ If you want to persist to something other than a file, create your own
55
+ metadata cache object and pass it in. It should have the same interface
56
+ as the built-in Metadata::FileCache class:
57
+
58
+ class MyMetadataCache
59
+
60
+ # Save the metadata. Should yield an IO-like object to a block;
61
+ # that block will serialize the metadata to that object.
62
+ def save(&block)
63
+ end
64
+
65
+ # Load the metadata. Should yield an IO-like object to a block;
66
+ # that block will deserialize the metadata from that object and
67
+ # return the metadata. Returns the metadata, or nil if it could
68
+ # not be loaded.
69
+ def load(&block)
70
+ end
71
+
72
+ end
73
+
74
+ By default, the metadata is serialized using Marshal. You may select
75
+ JSON or YAML instead, or define your own serialization mechanism, using the
76
+ :metadata_serializer option when you create the Rets::Client:
77
+
78
+ client = Rets::Client.new(
79
+ ...
80
+ metadata_serializer: Rets::Metadata::JsonSerializer.new
81
+ )
82
+
83
+ The built-in serializers are:
84
+
85
+ * Rets::Metadata::JsonSerializer
86
+ * Rets::Metadata::MarshalSerializer
87
+ * Rets::Metadata::YamlSerializer
88
+
89
+ To define your own serializer, create an object with this interface:
90
+
91
+ class MySerializer
92
+
93
+ # Serialize to a file. The library reserves the right to change
94
+ # the type or contents of o, so don't depend on it being
95
+ # anything in particular.
96
+ def save(file, o)
97
+ end
98
+
99
+ # Deserialize from a file. If the metadata cannot be
100
+ # deserialized, return nil.
101
+ def load(file)
102
+ end
103
+
104
+ end
105
+
106
+ ## LICENSE:
107
+
108
+ (The MIT License)
109
+
110
+ Copyright (c) 2011 Estately, Inc. <opensource@estately.com>
111
+
112
+ Permission is hereby granted, free of charge, to any person obtaining
113
+ a copy of this software and associated documentation files (the
114
+ 'Software'), to deal in the Software without restriction, including
115
+ without limitation the rights to use, copy, modify, merge, publish,
116
+ distribute, sublicense, and/or sell copies of the Software, and to
117
+ permit persons to whom the Software is furnished to do so, subject to
118
+ the following conditions:
119
+
120
+ The above copyright notice and this permission notice shall be included
121
+ in all copies or substantial portions of the Software.
122
+
123
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
124
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
125
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
126
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
127
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
128
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
129
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,28 @@
1
+ require 'rubygems'
2
+ require 'hoe'
3
+ require 'rake/testtask'
4
+
5
+ Hoe.plugin :git, :doofus
6
+ Hoe.plugin :travis
7
+ Hoe.plugin :gemspec
8
+
9
+ Hoe.spec 'rets' do
10
+ developer 'Estately, Inc. Open Source', 'opensource@estately.com'
11
+
12
+ extra_deps << [ "httpclient", "~> 2.7.0" ]
13
+ extra_deps << [ "http-cookie", "~> 1.0.0" ]
14
+ extra_deps << [ "nokogiri", "~> 1.5" ]
15
+
16
+ extra_dev_deps << [ "mocha", "~> 1.1.0" ]
17
+ extra_dev_deps << [ "vcr", "~> 2.2" ]
18
+ extra_dev_deps << [ "webmock", "~> 1.8" ]
19
+
20
+ ### Use markdown for changelog and readme
21
+ self.history_file = 'CHANGELOG.md'
22
+ self.readme_file = 'README.md'
23
+ end
24
+
25
+
26
+ Rake::TestTask.new do |t|
27
+ t.pattern = "test/test_*.rb"
28
+ end
data/bin/rets ADDED
@@ -0,0 +1,202 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "optparse"
4
+ require "pp"
5
+
6
+ require "rubygems"
7
+
8
+ $:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
9
+ require "rets"
10
+
11
+ class RetsCli
12
+ def self.parse(args)
13
+
14
+ actions = %w(metadata search count object)
15
+ options = {:count => 5}
16
+
17
+ opts = OptionParser.new do |opts|
18
+ opts.banner = "Usage: #{File.basename($0)} URL [options] [query]"
19
+
20
+ opts.separator ""
21
+ opts.separator "Authentication options:"
22
+
23
+ opts.on("-U", "--username USERNAME", "The username to authenticate with.") do |username|
24
+ options[:username] = username
25
+ end
26
+
27
+ opts.on("-P", "--password [PASSWORD]", "The password to authenticate with.","Prompts if no argument is provided.") do |password|
28
+ options[:password] = password #or prompt # TODO
29
+ end
30
+
31
+ opts.on("-A", "--agent AGENT", "User-Agent header to provide.") do |agent|
32
+ options[:agent] = agent
33
+ end
34
+
35
+ opts.on("-B", "--agent-password [PASSWORD]", "User-Agent password to provide.") do |ua_password|
36
+ options[:ua_password] = ua_password
37
+ end
38
+
39
+ opts.separator ""
40
+ opts.separator "Actions:"
41
+
42
+ opts.on("-p", "--capabilities", "Print capabilities of the RETS server.") do |capabilities|
43
+ options[:capabilities] = capabilities
44
+ end
45
+
46
+ opts.on("-a", "--action ACTION", actions, "Action to perform (#{actions.join(",")}).") do |action|
47
+ options[:action] = action
48
+ end
49
+
50
+ opts.on("-m", "--metadata [FORMAT]", %w(tree long short), "Print metadata.", "Format is short, long or tree.", "Defaults to short.") do |format|
51
+ options[:action] = "metadata"
52
+ options[:metadata_format] = format || "short"
53
+ end
54
+
55
+ opts.separator ""
56
+ opts.separator "Search action options:"
57
+
58
+ opts.on("-r", "--resource NAME", "Name of resource to search for.") do |name|
59
+ options[:resource] = name
60
+ end
61
+
62
+ opts.on("-c", "--class NAME", "Name of class to search for.") do |name|
63
+ options[:class] = name
64
+ end
65
+
66
+ opts.on("-n", "--number LIMIT", Integer, "Return LIMIT results. Defaults to 5.") do |limit|
67
+ options[:limit] = limit
68
+ end
69
+
70
+ opts.separator ""
71
+ opts.separator "Misc options:"
72
+
73
+ opts.on_tail("-v", "--verbose", "Be verbose.") do |verbose|
74
+ logger = Class.new do
75
+ def method_missing(method, *a, &b)
76
+ puts a
77
+ end
78
+ end
79
+
80
+ options[:logger] = logger.new
81
+ end
82
+
83
+ opts.on_tail("-h", "--help", "Show this message") do
84
+ puts opts
85
+ exit
86
+ end
87
+
88
+ opts.on_tail("--version", "Show version") do
89
+ puts Rets::VERSION
90
+ exit
91
+ end
92
+
93
+ end
94
+
95
+ begin
96
+ opts.parse!(args.empty? ? ["-h"] : args)
97
+ rescue OptionParser::InvalidArgument => e
98
+ abort e.message
99
+ end
100
+
101
+ options
102
+ end
103
+
104
+ end
105
+
106
+ options = RetsCli.parse(ARGV)
107
+ url = ARGV[0] or abort "Need login URL"
108
+ query = ARGV[1]
109
+
110
+ client = Rets::Client.new(options.merge(:login_url => url))
111
+
112
+ if options[:capabilities]
113
+ pp client.capabilities
114
+ end
115
+
116
+ case options[:action]
117
+ when "metadata" then
118
+ metadata = client.metadata
119
+
120
+ if options[:metadata_format] != "tree"
121
+ preferred_fields = %w(ClassName SystemName ResourceID StandardName VisibleName MetadataEntryID KeyField)
122
+
123
+
124
+ # All types except system
125
+ types = Rets::METADATA_TYPES.map { |t| t.downcase.to_sym } - [:system]
126
+
127
+ types.each do |type|
128
+ # if RowContainer ...
129
+ rows = metadata[type]
130
+
131
+ puts type.to_s.capitalize
132
+ puts "="*40
133
+
134
+ print_key_value = lambda do |k,v|
135
+ key = "#{k}:".ljust(35)
136
+ value = "#{v}".ljust(35)
137
+
138
+ puts [key, value].join
139
+ end
140
+
141
+ rows.each do |row|
142
+ top, rest = row.partition { |k,v| preferred_fields.include?(k) }
143
+
144
+ top.each(&print_key_value)
145
+
146
+ rest.sort_by{|k,v|k}.each(&print_key_value) if options[:metadata_format] == "long"
147
+
148
+ puts
149
+ end
150
+
151
+ puts
152
+ end
153
+
154
+ # Tree format
155
+ else
156
+ metadata.print_tree
157
+ end
158
+
159
+ when "search" then
160
+ pp client.find(:all,
161
+ :search_type => options[:resource],
162
+ :class => options[:class],
163
+ :query => query,
164
+ :count => Rets::Client::COUNT.exclude,
165
+ :limit => options[:limit])
166
+
167
+ when "count" then
168
+ pp client.find(:all,
169
+ :search_type => options[:resource],
170
+ :class => options[:class],
171
+ :query => query,
172
+ :count => Rets::Client::COUNT.only,
173
+ :limit => options[:limit])
174
+
175
+ when "object" then
176
+
177
+ def write_objects(parts)
178
+ parts.each do |part|
179
+ cid = part.headers["content-id"].to_i
180
+ oid = part.headers["object-id"].to_i
181
+
182
+ File.open("tmp/#{cid}-#{oid}", "wb") do |f|
183
+ puts f.path
184
+
185
+ f.write part.body
186
+ end
187
+ end
188
+ end
189
+
190
+ parts = client.all_objects(
191
+ :resource => "Property",
192
+ :resource_id => 90020062739, # id from KeyField for a given property
193
+ :object_type => "Photo"
194
+ )
195
+
196
+ parts.each { |pt| p pt.headers }
197
+
198
+ write_objects(parts)
199
+
200
+ end
201
+
202
+ client.logout
@@ -0,0 +1,19 @@
1
+ require 'rets'
2
+
3
+ # Pass the :login_url, :username, :password and :version of RETS
4
+ client = Rets::Client.new({
5
+ login_url: 'login_url',
6
+ username: 'xxx',
7
+ password: 'xxx',
8
+ version: 'RETS/1.5'
9
+ })
10
+
11
+ begin
12
+ client.login
13
+ rescue => e
14
+ puts 'Error: ' + e.message
15
+ exit!
16
+ end
17
+
18
+ puts 'We connected! Lets log out...'
19
+ client.logout
@@ -0,0 +1,20 @@
1
+ require 'rets'
2
+
3
+
4
+ # Get all photos (*) for MLS ID 'mls_id'
5
+ # Pass :object_id (ie '0', '1,2', wildcard '*')
6
+ # The pass :resource (Property, Agent, MetaData, ...), :object_type (Photo, PhotoLarge), :rescource_id (ID of agent, MLS, ...)
7
+ photos = client.objects '*', {
8
+ resource: 'Property',
9
+ object_type: 'Photo',
10
+ resource_id: 'mls_id'
11
+ }
12
+
13
+ photos.each_with_index do |data, index|
14
+ File.open("property-#{index.to_s}.jpg", 'w') do |file|
15
+ file.write data.body
16
+ end
17
+ end
18
+
19
+ puts photos.length.to_s + ' photos saved.'
20
+ client.logout
@@ -0,0 +1,16 @@
1
+ require 'rets'
2
+
3
+
4
+ # Get one property
5
+ # Pass :first or :all
6
+ # Then :search_type (Property, Agent, ...), :class (Condo, Commerical, ...), :query and :limit
7
+ property = client.find :first, {
8
+ search_type: 'Property',
9
+ class: 'CLASS_NAME',
10
+ query: 'RETS_QUERY',
11
+ limit: 1
12
+ }
13
+
14
+ puts 'received property: '
15
+ puts property.inspect
16
+ client.logout