flexmls_api 0.3.3 → 0.3.6
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/lib/flexmls_api.rb +1 -0
- data/lib/flexmls_api/authentication.rb +1 -1
- data/lib/flexmls_api/configuration.rb +3 -1
- data/lib/flexmls_api/faraday.rb +2 -1
- data/lib/flexmls_api/models.rb +2 -0
- data/lib/flexmls_api/models/account.rb +55 -0
- data/lib/flexmls_api/models/base.rb +1 -1
- data/lib/flexmls_api/models/finders.rb +45 -0
- data/lib/flexmls_api/models/idx_link.rb +2 -0
- data/lib/flexmls_api/models/listing.rb +6 -34
- data/lib/flexmls_api/primary_array.rb +29 -0
- data/lib/flexmls_api/request.rb +7 -2
- data/spec/unit/flexmls_api/configuration_spec.rb +19 -15
- data/spec/unit/flexmls_api/models/account_spec.rb +96 -0
- data/spec/unit/flexmls_api/models/contact_spec.rb +6 -6
- data/spec/unit/flexmls_api/paginate_spec.rb +71 -71
- data/spec/unit/flexmls_api/primary_array_spec.rb +41 -0
- data/spec/unit/flexmls_api/request_spec.rb +14 -10
- metadata +12 -4
data/Rakefile
CHANGED
@@ -13,7 +13,7 @@ begin
|
|
13
13
|
gemspec.description = "A library for interacting with the flexmls web services."
|
14
14
|
gemspec.email = "api-support@flexmls.com"
|
15
15
|
gemspec.homepage = "https://github.com/flexmls/flexmls_api"
|
16
|
-
gemspec.authors = ["Brandon Hornseth"]
|
16
|
+
gemspec.authors = ["Brandon Hornseth", "Wade McEwen"]
|
17
17
|
gemspec.files = FileList["[A-Z]*", "{lib,spec}/**/*"]
|
18
18
|
gemspec.add_development_dependency "rspec"
|
19
19
|
gemspec.add_development_dependency "jeweler"
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.3.
|
1
|
+
0.3.6
|
data/lib/flexmls_api.rb
CHANGED
@@ -11,6 +11,7 @@ require File.expand_path('../flexmls_api/paginate', __FILE__)
|
|
11
11
|
require File.expand_path('../flexmls_api/request', __FILE__)
|
12
12
|
require File.expand_path('../flexmls_api/client', __FILE__)
|
13
13
|
require File.expand_path('../flexmls_api/faraday', __FILE__)
|
14
|
+
require File.expand_path('../flexmls_api/primary_array', __FILE__)
|
14
15
|
require File.expand_path('../flexmls_api/models', __FILE__)
|
15
16
|
|
16
17
|
module FlexmlsApi
|
@@ -22,7 +22,7 @@ module FlexmlsApi
|
|
22
22
|
request_path = "/#{version}/session?ApiKey=#{api_key}&ApiSig=#{sig}"
|
23
23
|
resp = connection(true).post request_path, ""
|
24
24
|
request_time = Time.now - start_time
|
25
|
-
FlexmlsApi.logger.info("[#{request_time}
|
25
|
+
FlexmlsApi.logger.info("[#{(request_time * 1000).to_i}ms] Api: POST #{request_path}")
|
26
26
|
@session = Session.new(resp.body.results[0])
|
27
27
|
FlexmlsApi.logger.debug("Authentication: #{@session.inspect}")
|
28
28
|
@session
|
@@ -1,10 +1,11 @@
|
|
1
1
|
module FlexmlsApi
|
2
2
|
module Configuration
|
3
3
|
# valid configuration options
|
4
|
-
VALID_OPTION_KEYS = [:api_key, :api_secret, :endpoint, :user_agent, :version, :ssl].freeze
|
4
|
+
VALID_OPTION_KEYS = [:api_key, :api_secret, :api_user, :endpoint, :user_agent, :version, :ssl].freeze
|
5
5
|
|
6
6
|
DEFAULT_API_KEY = nil
|
7
7
|
DEFAULT_API_SECRET = nil
|
8
|
+
DEFAULT_API_USER = nil
|
8
9
|
DEFAULT_ENDPOINT = 'http://api.flexmls.com'
|
9
10
|
DEFAULT_VERSION = 'v1'
|
10
11
|
DEFAULT_USER_AGENT = "flexmls API Ruby Gem #{VERSION}"
|
@@ -30,6 +31,7 @@ module FlexmlsApi
|
|
30
31
|
def reset_configuration
|
31
32
|
self.api_key = DEFAULT_API_KEY
|
32
33
|
self.api_secret = DEFAULT_API_SECRET
|
34
|
+
self.api_user = DEFAULT_API_USER
|
33
35
|
self.endpoint = DEFAULT_ENDPOINT
|
34
36
|
self.version = DEFAULT_VERSION
|
35
37
|
self.user_agent = DEFAULT_USER_AGENT
|
data/lib/flexmls_api/faraday.rb
CHANGED
@@ -17,7 +17,7 @@ module FlexmlsApi
|
|
17
17
|
# indicate a failure will raise a FlexmlsApi::ClientError exception
|
18
18
|
def self.validate_and_build_response(finished_env)
|
19
19
|
body = finished_env[:body]
|
20
|
-
FlexmlsApi.logger.debug("Response Body: #{body
|
20
|
+
FlexmlsApi.logger.debug("Response Body: #{body}")
|
21
21
|
unless body.is_a?(Hash) && body.key?("D")
|
22
22
|
raise InvalidResponse, "The server response could not be understood"
|
23
23
|
end
|
@@ -47,5 +47,6 @@ module FlexmlsApi
|
|
47
47
|
end
|
48
48
|
|
49
49
|
end
|
50
|
+
|
50
51
|
end
|
51
52
|
end
|
data/lib/flexmls_api/models.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
require File.expand_path('../models/base', __FILE__)
|
2
|
+
require File.expand_path('../models/finders', __FILE__)
|
3
|
+
require File.expand_path('../models/account', __FILE__)
|
2
4
|
require File.expand_path('../models/listing', __FILE__)
|
3
5
|
require File.expand_path('../models/subresource', __FILE__)
|
4
6
|
require File.expand_path('../models/photo', __FILE__)
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module FlexmlsApi
|
2
|
+
module Models
|
3
|
+
class Account < Base
|
4
|
+
self.element_name="accounts"
|
5
|
+
|
6
|
+
SUBELEMENTS = [:emails, :phones, :websites, :addresses, :images]
|
7
|
+
attr_accessor *SUBELEMENTS
|
8
|
+
|
9
|
+
def initialize(attributes={})
|
10
|
+
@emails = subresource(Email, "Emails", attributes)
|
11
|
+
@phones = subresource(Phone, "Phones", attributes)
|
12
|
+
@websites = subresource(Website, "Websites", attributes)
|
13
|
+
@addresses = subresource(Address, "Addresses", attributes)
|
14
|
+
@images = subresource(Image, "Images", attributes)
|
15
|
+
super(attributes)
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.my(arguments={})
|
19
|
+
collect(connection.get("/my/account", arguments)).first
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def subresource(klass, key, attributes)
|
25
|
+
return nil unless attributes.key?(key)
|
26
|
+
array = attributes[key]
|
27
|
+
result = PrimaryArray.new()
|
28
|
+
array.each do |i|
|
29
|
+
result << klass.new(i)
|
30
|
+
end
|
31
|
+
result
|
32
|
+
end
|
33
|
+
|
34
|
+
class Email < Base
|
35
|
+
include Primary
|
36
|
+
end
|
37
|
+
|
38
|
+
class Phone < Base
|
39
|
+
include Primary
|
40
|
+
end
|
41
|
+
|
42
|
+
class Website < Base
|
43
|
+
include Primary
|
44
|
+
end
|
45
|
+
|
46
|
+
class Address < Base
|
47
|
+
include Primary
|
48
|
+
end
|
49
|
+
class Image < Base
|
50
|
+
include Primary
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module FlexmlsApi
|
2
|
+
module Models
|
3
|
+
# =Rails-like finders module
|
4
|
+
# Adds the base set of finder class methods to the models that support them (not all of them do)
|
5
|
+
module Finders
|
6
|
+
|
7
|
+
def find(*arguments)
|
8
|
+
scope = arguments.slice!(0)
|
9
|
+
options = arguments.slice!(0) || {}
|
10
|
+
case scope
|
11
|
+
when :all then find_every(options)
|
12
|
+
when :first then find_every(options).first
|
13
|
+
when :last then find_every(options).last
|
14
|
+
when :one then find_one(options)
|
15
|
+
else find_single(scope, options)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def first(*arguments)
|
20
|
+
find(:first, *arguments)
|
21
|
+
end
|
22
|
+
|
23
|
+
def last(*arguments)
|
24
|
+
find(:last, *arguments)
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def find_every(options)
|
30
|
+
collect(connection.get("/#{element_name}", options))
|
31
|
+
end
|
32
|
+
|
33
|
+
def find_one(options)
|
34
|
+
raise NotImplementedError # TODO um... what?
|
35
|
+
end
|
36
|
+
|
37
|
+
def find_single(scope, options)
|
38
|
+
resp = connection.get("/#{element_name}/#{scope}", options)
|
39
|
+
new(resp[0])
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
@@ -1,6 +1,7 @@
|
|
1
1
|
module FlexmlsApi
|
2
2
|
module Models
|
3
3
|
class Listing < Base
|
4
|
+
extend Finders
|
4
5
|
attr_accessor :photos, :videos, :virtual_tours, :documents
|
5
6
|
self.element_name="listings"
|
6
7
|
|
@@ -39,53 +40,24 @@ module FlexmlsApi
|
|
39
40
|
super(attributes)
|
40
41
|
end
|
41
42
|
|
42
|
-
|
43
|
-
def self.find(*arguments)
|
44
|
-
scope = arguments.slice!(0)
|
45
|
-
options = arguments.slice!(0) || {}
|
46
|
-
|
47
|
-
case scope
|
48
|
-
when :all then find_every(options)
|
49
|
-
when :first then find_every(options).first
|
50
|
-
when :last then find_every(options).last
|
51
|
-
when :one then find_one(options)
|
52
|
-
else find_single(scope, options)
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
43
|
def self.find_by_cart_id(cart_id, owner, options={})
|
57
44
|
options.merge!({ :ApiUser => owner, :_filter => "ListingCart Eq '#{cart_id}'" })
|
58
45
|
find(:all, options)
|
59
46
|
end
|
60
47
|
|
61
|
-
def self.first(*arguments)
|
62
|
-
find(:first, *arguments)
|
63
|
-
end
|
64
|
-
|
65
|
-
def self.last(*arguments)
|
66
|
-
find(:last, *arguments)
|
67
|
-
end
|
68
|
-
|
69
48
|
def self.my(arguments={})
|
70
49
|
collect(connection.get("/my/listings", arguments))
|
71
50
|
end
|
72
51
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
def self.find_every(options)
|
77
|
-
collect(connection.get('/listings', options))
|
52
|
+
def self.office(arguments={})
|
53
|
+
collect(connection.get("/office/listings", arguments))
|
78
54
|
end
|
79
55
|
|
80
|
-
def self.
|
81
|
-
|
82
|
-
end
|
83
|
-
|
84
|
-
def self.find_single(scope, options)
|
85
|
-
resp = FlexmlsApi.client.get("/listings/#{scope}", options)
|
86
|
-
new(resp[0])
|
56
|
+
def self.company(arguments={})
|
57
|
+
collect(connection.get("/company/listings", arguments))
|
87
58
|
end
|
88
59
|
|
60
|
+
private
|
89
61
|
|
90
62
|
# TODO trim this down so we're only overriding the StandardFields access
|
91
63
|
def method_missing(method_symbol, *arguments)
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module FlexmlsApi
|
2
|
+
class PrimaryArray < Array
|
3
|
+
|
4
|
+
def primary
|
5
|
+
find_primary
|
6
|
+
end
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
# This is a very simplistic but reliable implementation.
|
11
|
+
def find_primary
|
12
|
+
self.each do |arg|
|
13
|
+
if arg.primary?
|
14
|
+
return arg
|
15
|
+
end
|
16
|
+
end
|
17
|
+
nil
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
#=== Primary: interface to implement for elements that are added to a "PrimaryArray" collection
|
22
|
+
module Primary
|
23
|
+
# Return true if the element is the primary resource in a collection.
|
24
|
+
# Default implementation looks for a "Primary" attribute
|
25
|
+
def primary?
|
26
|
+
@attributes.key?("Primary") && self.Primary == true
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/flexmls_api/request.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'cgi'
|
1
2
|
|
2
3
|
module FlexmlsApi
|
3
4
|
# HTTP request wrapper. Performs all the api session mumbo jumbo so that the models don't have to.
|
@@ -65,6 +66,9 @@ module FlexmlsApi
|
|
65
66
|
request_opts = {
|
66
67
|
"AuthToken" => @session.auth_token
|
67
68
|
}
|
69
|
+
unless self.api_user.nil?
|
70
|
+
request_opts.merge!(:ApiUser => "#{api_user}")
|
71
|
+
end
|
68
72
|
request_opts.merge!(options)
|
69
73
|
post_data = body.nil? ? nil : {"D" => body }.to_json
|
70
74
|
sig = sign_token(path, request_opts, post_data)
|
@@ -78,7 +82,7 @@ module FlexmlsApi
|
|
78
82
|
response = connection.send(method, request_path, post_data)
|
79
83
|
end
|
80
84
|
request_time = Time.now - start_time
|
81
|
-
FlexmlsApi.logger.info("[#{request_time}
|
85
|
+
FlexmlsApi.logger.info("[#{(request_time * 1000).to_i}ms] Api: #{method.to_s.upcase} #{request_path}")
|
82
86
|
rescue PermissionDenied => e
|
83
87
|
if(ResponseCodes::SESSION_TOKEN_EXPIRED == e.code)
|
84
88
|
unless (attempts +=1) > 1
|
@@ -106,7 +110,8 @@ module FlexmlsApi
|
|
106
110
|
def build_url_parameters(parameters={})
|
107
111
|
str = ""
|
108
112
|
parameters.map do |key,value|
|
109
|
-
|
113
|
+
escaped_value = CGI.escape("#{value}")
|
114
|
+
str << "&#{key}=#{escaped_value}"
|
110
115
|
end
|
111
116
|
str
|
112
117
|
end
|
@@ -9,11 +9,11 @@ describe FlexmlsApi::Client, "Client config" do
|
|
9
9
|
it "should return the proper defaults when called with no arguments" do
|
10
10
|
FlexmlsApi.api_key.should be_nil
|
11
11
|
FlexmlsApi.api_secret.should be_nil
|
12
|
-
FlexmlsApi.version.should match
|
13
|
-
FlexmlsApi.endpoint.should match
|
12
|
+
FlexmlsApi.version.should match("v1")
|
13
|
+
FlexmlsApi.endpoint.should match("api.flexmls.com")
|
14
14
|
|
15
15
|
FlexmlsApi.api_key = "my_api_key"
|
16
|
-
FlexmlsApi.api_key.should match
|
16
|
+
FlexmlsApi.api_key.should match("my_api_key")
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
@@ -21,12 +21,14 @@ describe FlexmlsApi::Client, "Client config" do
|
|
21
21
|
it "should return a properly configured client" do
|
22
22
|
client = FlexmlsApi::Client.new(:api_key => "key_of_wade",
|
23
23
|
:api_secret => "TopSecret",
|
24
|
+
:api_user => "1234",
|
24
25
|
:endpoint => "http://api.wade.dev.fbsdata.com")
|
25
26
|
|
26
|
-
client.api_key.should match
|
27
|
-
client.api_secret.should match
|
28
|
-
client.
|
29
|
-
client.
|
27
|
+
client.api_key.should match("key_of_wade")
|
28
|
+
client.api_secret.should match("TopSecret")
|
29
|
+
client.api_user.should match("1234")
|
30
|
+
client.endpoint.should match("http://api.wade.dev.fbsdata.com")
|
31
|
+
client.version.should match("v1")
|
30
32
|
end
|
31
33
|
end
|
32
34
|
|
@@ -35,16 +37,18 @@ describe FlexmlsApi::Client, "Client config" do
|
|
35
37
|
FlexmlsApi.configure do |config|
|
36
38
|
config.api_key = "my_key"
|
37
39
|
config.api_secret = "my_secret"
|
40
|
+
config.api_user = "1234"
|
38
41
|
config.version = "veleventy"
|
39
42
|
config.endpoint = "test.api.flexmls.com"
|
40
43
|
config.user_agent = "my useragent"
|
41
44
|
end
|
42
45
|
|
43
|
-
FlexmlsApi.api_key.should match
|
44
|
-
FlexmlsApi.api_secret.should match
|
45
|
-
FlexmlsApi.
|
46
|
-
FlexmlsApi.
|
47
|
-
FlexmlsApi.
|
46
|
+
FlexmlsApi.api_key.should match("my_key")
|
47
|
+
FlexmlsApi.api_secret.should match("my_secret")
|
48
|
+
FlexmlsApi.api_user.should match("1234")
|
49
|
+
FlexmlsApi.version.should match("veleventy")
|
50
|
+
FlexmlsApi.endpoint.should match("test.api.flexmls.com")
|
51
|
+
FlexmlsApi.user_agent.should match("my useragent")
|
48
52
|
|
49
53
|
end
|
50
54
|
|
@@ -57,7 +61,7 @@ describe FlexmlsApi::Client, "Client config" do
|
|
57
61
|
config.user_agent = "my useragent"
|
58
62
|
end
|
59
63
|
|
60
|
-
FlexmlsApi.api_key.should match
|
64
|
+
FlexmlsApi.api_key.should match("my_key")
|
61
65
|
FlexmlsApi.reset
|
62
66
|
FlexmlsApi.api_key.should == FlexmlsApi::Configuration::DEFAULT_API_KEY
|
63
67
|
|
@@ -74,7 +78,7 @@ describe FlexmlsApi::Client, "Client config" do
|
|
74
78
|
}).
|
75
79
|
to_return(:body => '{"D":{"Success": true,"Results": [{"SSL":false}]}}')
|
76
80
|
|
77
|
-
FlexmlsApi.client.get('/connections')[0]["SSL"].should eq
|
81
|
+
FlexmlsApi.client.get('/connections')[0]["SSL"].should eq(false)
|
78
82
|
|
79
83
|
end
|
80
84
|
|
@@ -88,7 +92,7 @@ describe FlexmlsApi::Client, "Client config" do
|
|
88
92
|
to_return(:body => '{"D":{"Success": true,"Results": [{"SSL":true}]}}')
|
89
93
|
c = FlexmlsApi::Client.new(:endpoint => "https://api.flexmls.com",
|
90
94
|
:ssl => true)
|
91
|
-
c.get('/connections')[0]["SSL"].should eq
|
95
|
+
c.get('/connections')[0]["SSL"].should eq(true)
|
92
96
|
end
|
93
97
|
|
94
98
|
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
require './spec/spec_helper'
|
2
|
+
|
3
|
+
describe Account do
|
4
|
+
before(:each) do
|
5
|
+
@account = Account.new({
|
6
|
+
"Name"=>"Sample User",
|
7
|
+
"Id"=>"20000426173054342350000000",
|
8
|
+
"Office"=>"Sample Office",
|
9
|
+
"Mls"=>"Sample MLS",
|
10
|
+
"MlsId"=>"20000426143505724628000000",
|
11
|
+
"Emails"=>[
|
12
|
+
{
|
13
|
+
"Type"=>"Work",
|
14
|
+
"Name"=>"My Work E-mail",
|
15
|
+
"Address"=>"work@test.com",
|
16
|
+
"Primary"=>true
|
17
|
+
},
|
18
|
+
{
|
19
|
+
"Type"=>"Home",
|
20
|
+
"Name"=>"My Home E-mail",
|
21
|
+
"Address"=>"home@test.com"
|
22
|
+
}
|
23
|
+
],
|
24
|
+
"Phones"=>[
|
25
|
+
{
|
26
|
+
"Type"=>"Work",
|
27
|
+
"Name"=>"My Work Phone",
|
28
|
+
"Number"=>"701-555-1212",
|
29
|
+
"Primary"=>true
|
30
|
+
},
|
31
|
+
{
|
32
|
+
"Type"=>"Home",
|
33
|
+
"Name"=>"My Home Phone",
|
34
|
+
"Number"=>"702-555-1313"
|
35
|
+
}
|
36
|
+
],
|
37
|
+
"Websites"=>[
|
38
|
+
{
|
39
|
+
"Type"=>"Work",
|
40
|
+
"Name"=>"My Work Website",
|
41
|
+
"Uri"=>"http://iamthebestagent.com",
|
42
|
+
"Primary"=>true
|
43
|
+
},
|
44
|
+
{
|
45
|
+
"Type"=>"Home",
|
46
|
+
"Name"=>"My Home Website",
|
47
|
+
"Uri"=>"http://myspace.com/lolcats"
|
48
|
+
}
|
49
|
+
],
|
50
|
+
"Addresses"=>[
|
51
|
+
{
|
52
|
+
"Type"=>"Work",
|
53
|
+
"Name"=>"My Work Address",
|
54
|
+
"Address"=>"101 Main Ave, Phoenix, AZ 12345",
|
55
|
+
"Primary"=>true
|
56
|
+
},
|
57
|
+
{
|
58
|
+
"Type"=>"Home",
|
59
|
+
"Name"=>"My Home Address",
|
60
|
+
"Address"=>"102 Main Ave, Gilbert, AZ 54321"
|
61
|
+
}
|
62
|
+
],
|
63
|
+
"Images"=>[
|
64
|
+
{
|
65
|
+
"Type"=>"Photo",
|
66
|
+
"Name"=>"My Photo",
|
67
|
+
"Uri"=>"http://photos.flexmls.com/az/...."
|
68
|
+
},
|
69
|
+
{
|
70
|
+
"Type"=>"Logo",
|
71
|
+
"Name"=>"My Logo",
|
72
|
+
"Uri"=>"http://photos.flexmls.com/az/...."
|
73
|
+
}
|
74
|
+
]
|
75
|
+
})
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should respond to attributes" do
|
79
|
+
['Name','Id','Mls','MlsId','Office'].each do |k|
|
80
|
+
(@account.send k.to_sym).should be_a(String)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should have primary subresources" do
|
85
|
+
@account.emails.primary.Address.should eq("work@test.com")
|
86
|
+
@account.phones.primary.Number.should eq("701-555-1212")
|
87
|
+
@account.addresses.primary.Address.should eq("101 Main Ave, Phoenix, AZ 12345")
|
88
|
+
@account.websites.primary.Uri.should eq("http://iamthebestagent.com")
|
89
|
+
@account.images.primary.should be(nil)
|
90
|
+
end
|
91
|
+
|
92
|
+
after(:each) do
|
93
|
+
@acount = nil
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
@@ -31,22 +31,22 @@ describe Contact do
|
|
31
31
|
|
32
32
|
it "should get all my contacts" do
|
33
33
|
contacts = Contact.get
|
34
|
-
contacts.should be_an
|
35
|
-
contacts.length.should eq
|
36
|
-
contacts.first.Id.should eq
|
34
|
+
contacts.should be_an(Array)
|
35
|
+
contacts.length.should eq(3)
|
36
|
+
contacts.first.Id.should eq("20101230223226074201000000")
|
37
37
|
end
|
38
38
|
|
39
39
|
it "should save a new contact" do
|
40
40
|
c=Contact.new
|
41
41
|
c.attributes["DisplayName"] = "Contact Four"
|
42
42
|
c.attributes["PrimaryEmail"] = "contact4@fbsdata.com"
|
43
|
-
c.save.should be
|
44
|
-
c.Id.should eq
|
43
|
+
c.save.should be(true)
|
44
|
+
c.Id.should eq('20101230223226074204000000')
|
45
45
|
end
|
46
46
|
|
47
47
|
it "should fail saving" do
|
48
48
|
c=Contact.new
|
49
|
-
c.save.should be
|
49
|
+
c.save.should be(false)
|
50
50
|
expect{ c.save! }.to raise_error(FlexmlsApi::ClientError){ |e| e.status.should == 400 }
|
51
51
|
end
|
52
52
|
|
@@ -38,54 +38,54 @@ describe FlexmlsApi::PaginateResponse do
|
|
38
38
|
json = "{#{paginate_json}}"
|
39
39
|
hash = JSON.parse(json)
|
40
40
|
results = subject.paginate_response([1,2,3,4,5,6,7,8,9,10], hash["Pagination"])
|
41
|
-
results.offset.should eq
|
42
|
-
results.next_page.should eq
|
43
|
-
results.previous_page.should eq
|
44
|
-
results.current_page.should eq
|
45
|
-
results.per_page.should eq
|
46
|
-
results.total_pages.should eq
|
47
|
-
results.total_entries.should eq
|
48
|
-
results[0].should eq
|
41
|
+
results.offset.should eq(0)
|
42
|
+
results.next_page.should eq(2)
|
43
|
+
results.previous_page.should eq(nil)
|
44
|
+
results.current_page.should eq(1)
|
45
|
+
results.per_page.should eq(10)
|
46
|
+
results.total_pages.should eq(4)
|
47
|
+
results.total_entries.should eq(38)
|
48
|
+
results[0].should eq(1)
|
49
49
|
end
|
50
50
|
it "should give me the second page" do
|
51
51
|
json = "{#{paginate_json(2)}}"
|
52
52
|
hash = JSON.parse(json)
|
53
53
|
results = subject.paginate_response([11,12,13,14,15,16,17,18,19,20], hash["Pagination"])
|
54
|
-
results.offset.should eq
|
55
|
-
results.next_page.should eq
|
56
|
-
results.previous_page.should eq
|
57
|
-
results.current_page.should eq
|
58
|
-
results.per_page.should eq
|
59
|
-
results.total_pages.should eq
|
60
|
-
results.total_entries.should eq
|
61
|
-
results[0].should eq
|
54
|
+
results.offset.should eq(10)
|
55
|
+
results.next_page.should eq(3)
|
56
|
+
results.previous_page.should eq(1)
|
57
|
+
results.current_page.should eq(2)
|
58
|
+
results.per_page.should eq(10)
|
59
|
+
results.total_pages.should eq(4)
|
60
|
+
results.total_entries.should eq(38)
|
61
|
+
results[0].should eq(11)
|
62
62
|
end
|
63
63
|
it "should give me the third page" do
|
64
64
|
json = "{#{paginate_json(3)}}"
|
65
65
|
hash = JSON.parse(json)
|
66
66
|
results = subject.paginate_response([21,22,23,24,25,26,27,28,29,30], hash["Pagination"])
|
67
|
-
results.offset.should eq
|
68
|
-
results.next_page.should eq
|
69
|
-
results.previous_page.should eq
|
70
|
-
results.current_page.should eq
|
71
|
-
results.per_page.should eq
|
72
|
-
results.total_pages.should eq
|
73
|
-
results.total_entries.should eq
|
74
|
-
results[0].should eq
|
67
|
+
results.offset.should eq(20)
|
68
|
+
results.next_page.should eq(4)
|
69
|
+
results.previous_page.should eq(2)
|
70
|
+
results.current_page.should eq(3)
|
71
|
+
results.per_page.should eq(10)
|
72
|
+
results.total_pages.should eq(4)
|
73
|
+
results.total_entries.should eq(38)
|
74
|
+
results[0].should eq(21)
|
75
75
|
end
|
76
76
|
it "should give me the last page" do
|
77
77
|
json = "{#{paginate_json(4)}}"
|
78
78
|
hash = JSON.parse(json)
|
79
79
|
results = subject.paginate_response([31,32,33,34,35,36,37,38], hash["Pagination"])
|
80
|
-
results.offset.should eq
|
81
|
-
results.next_page.should eq
|
82
|
-
results.previous_page.should eq
|
83
|
-
results.current_page.should eq
|
84
|
-
results.per_page.should eq
|
85
|
-
results.total_pages.should eq
|
86
|
-
results.total_entries.should eq
|
87
|
-
results[0].should eq
|
88
|
-
results[-1].should eq
|
80
|
+
results.offset.should eq(30)
|
81
|
+
results.next_page.should eq(nil)
|
82
|
+
results.previous_page.should eq(3)
|
83
|
+
results.current_page.should eq(4)
|
84
|
+
results.per_page.should eq(10)
|
85
|
+
results.total_pages.should eq(4)
|
86
|
+
results.total_entries.should eq(38)
|
87
|
+
results[0].should eq(31)
|
88
|
+
results[-1].should eq(38)
|
89
89
|
end
|
90
90
|
end
|
91
91
|
end
|
@@ -94,27 +94,27 @@ describe FlexmlsApi::Paginate do
|
|
94
94
|
describe "paginate" do
|
95
95
|
it "should give me a will paginate collection" do
|
96
96
|
results = PaginateModelTester.paginate(:page => 1)
|
97
|
-
results.class.should eq
|
98
|
-
results.offset.should eq
|
99
|
-
results.next_page.should eq
|
100
|
-
results.previous_page.should eq
|
101
|
-
results.current_page.should eq
|
102
|
-
results.per_page.should eq
|
103
|
-
results.total_pages.should eq
|
104
|
-
results.total_entries.should eq
|
97
|
+
results.class.should eq(WillPaginate::Collection)
|
98
|
+
results.offset.should eq(0)
|
99
|
+
results.next_page.should eq(2)
|
100
|
+
results.previous_page.should eq(nil)
|
101
|
+
results.current_page.should eq(1)
|
102
|
+
results.per_page.should eq(10)
|
103
|
+
results.total_pages.should eq(4)
|
104
|
+
results.total_entries.should eq(38)
|
105
105
|
|
106
|
-
results[0].class.should eq
|
107
|
-
results[0].val.should eq
|
106
|
+
results[0].class.should eq(PaginateModelTester)
|
107
|
+
results[0].val.should eq(1)
|
108
108
|
|
109
109
|
end
|
110
110
|
|
111
111
|
it "should give me pagination options" do
|
112
112
|
PaginateModelTester.paginate(:page => 1)
|
113
113
|
opts = PaginateModelTester.options
|
114
|
-
opts["_pagination"].should eq
|
115
|
-
opts["_limit"].should eq
|
116
|
-
opts["_page"].should eq
|
117
|
-
opts.has_key?(:page).should eq
|
114
|
+
opts["_pagination"].should eq(1)
|
115
|
+
opts["_limit"].should eq(25)
|
116
|
+
opts["_page"].should eq(1)
|
117
|
+
opts.has_key?(:page).should eq(false)
|
118
118
|
end
|
119
119
|
end
|
120
120
|
|
@@ -122,7 +122,7 @@ describe FlexmlsApi::Paginate do
|
|
122
122
|
it "should set the default model max results per page" do
|
123
123
|
results = PaginateModelTester50.paginate(:page => 1)
|
124
124
|
opts = PaginateModelTester50.options
|
125
|
-
opts["_limit"].should eq
|
125
|
+
opts["_limit"].should eq(50)
|
126
126
|
end
|
127
127
|
end
|
128
128
|
|
@@ -151,18 +151,18 @@ describe FlexmlsApi::Paginate do
|
|
151
151
|
}).
|
152
152
|
to_return(:body => json)
|
153
153
|
results = subject.paginate(:page=>1, :per_page=>10)
|
154
|
-
results.class.should eq
|
155
|
-
results.offset.should eq
|
156
|
-
results.next_page.should eq
|
157
|
-
results.previous_page.should eq
|
158
|
-
results.current_page.should eq
|
159
|
-
results.per_page.should eq
|
160
|
-
results.total_pages.should eq
|
161
|
-
results.total_entries.should eq
|
162
|
-
results.length.should eq
|
154
|
+
results.class.should eq(WillPaginate::Collection)
|
155
|
+
results.offset.should eq(0)
|
156
|
+
results.next_page.should eq(2)
|
157
|
+
results.previous_page.should eq(nil)
|
158
|
+
results.current_page.should eq(1)
|
159
|
+
results.per_page.should eq(10)
|
160
|
+
results.total_pages.should eq(4)
|
161
|
+
results.total_entries.should eq(38)
|
162
|
+
results.length.should eq(10)
|
163
163
|
|
164
|
-
results[0].class.should eq
|
165
|
-
results[0].ListPrice.should eq
|
164
|
+
results[0].class.should eq(subject)
|
165
|
+
results[0].ListPrice.should eq(50000.0)
|
166
166
|
|
167
167
|
end
|
168
168
|
it "gives me page two of listings" do
|
@@ -183,9 +183,9 @@ describe FlexmlsApi::Paginate do
|
|
183
183
|
}).
|
184
184
|
to_return(:body => json)
|
185
185
|
results = subject.paginate(:page=>2, :per_page=>10)
|
186
|
-
results.next_page.should eq
|
187
|
-
results.previous_page.should eq
|
188
|
-
results.current_page.should eq
|
186
|
+
results.next_page.should eq(3)
|
187
|
+
results.previous_page.should eq(1)
|
188
|
+
results.current_page.should eq(2)
|
189
189
|
end
|
190
190
|
it "gives me page four of listings" do
|
191
191
|
json = <<-JSON
|
@@ -205,16 +205,16 @@ describe FlexmlsApi::Paginate do
|
|
205
205
|
}).
|
206
206
|
to_return(:body => json)
|
207
207
|
results = subject.paginate(:page=>4, :per_page=>10)
|
208
|
-
results.next_page.should eq
|
209
|
-
results.previous_page.should eq
|
210
|
-
results.current_page.should eq
|
211
|
-
results.per_page.should eq
|
212
|
-
results.total_pages.should eq
|
213
|
-
results.total_entries.should eq
|
208
|
+
results.next_page.should eq(nil)
|
209
|
+
results.previous_page.should eq(3)
|
210
|
+
results.current_page.should eq(4)
|
211
|
+
results.per_page.should eq(10)
|
212
|
+
results.total_pages.should eq(4)
|
213
|
+
results.total_entries.should eq(38)
|
214
214
|
|
215
|
-
results.length.should eq
|
216
|
-
results[0].class.should eq
|
217
|
-
results[0].ListPrice.should eq
|
215
|
+
results.length.should eq(8)
|
216
|
+
results[0].class.should eq(subject)
|
217
|
+
results[0].ListPrice.should eq(50000.0)
|
218
218
|
end
|
219
219
|
|
220
220
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require './spec/spec_helper'
|
2
|
+
|
3
|
+
class PrimaryModel
|
4
|
+
include FlexmlsApi::Primary
|
5
|
+
attr_accessor :Primary, :id, :attributes
|
6
|
+
def initialize(id, prime = false)
|
7
|
+
@id = id
|
8
|
+
@Primary = prime
|
9
|
+
@attributes = {"Primary" => prime }
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe FlexmlsApi::PrimaryArray do
|
14
|
+
it "should give me the primary element" do
|
15
|
+
a = PrimaryModel.new(1)
|
16
|
+
b = PrimaryModel.new(2)
|
17
|
+
c = PrimaryModel.new(3)
|
18
|
+
d = PrimaryModel.new(4, true)
|
19
|
+
e = PrimaryModel.new(5)
|
20
|
+
tester = subject.class.new([d,e])
|
21
|
+
tester.primary.should eq(d)
|
22
|
+
tester = subject.class.new([a,b,c,d,e])
|
23
|
+
tester.primary.should eq(d)
|
24
|
+
# Note, it doesn't care if there is more than one primary, just returns first in the list.
|
25
|
+
b.Primary = true
|
26
|
+
tester.primary.should eq(b)
|
27
|
+
end
|
28
|
+
it "should return nil when there is no primary element" do
|
29
|
+
a = PrimaryModel.new(1)
|
30
|
+
b = PrimaryModel.new(2)
|
31
|
+
c = PrimaryModel.new(3)
|
32
|
+
d = PrimaryModel.new(4)
|
33
|
+
e = PrimaryModel.new(5)
|
34
|
+
tester = subject.class.new([])
|
35
|
+
tester.primary.should be(nil)
|
36
|
+
tester = subject.class.new([a,b,c,d,e])
|
37
|
+
tester.primary.should be(nil)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
|
@@ -21,12 +21,12 @@ describe FlexmlsApi do
|
|
21
21
|
end
|
22
22
|
it "should have results when successful" do
|
23
23
|
r = FlexmlsApi::ApiResponse.new({"D"=>{"Success" => true, "Results" => []}})
|
24
|
-
r.success?.should be
|
25
|
-
r.results.empty?.should be
|
24
|
+
r.success?.should be(true)
|
25
|
+
r.results.empty?.should be(true)
|
26
26
|
end
|
27
27
|
it "should have a message on error" do
|
28
28
|
r = FlexmlsApi::ApiResponse.new({"D"=>{"Success" => false, "Message" => "I am a failure."}})
|
29
|
-
r.success?.should be
|
29
|
+
r.success?.should be(false)
|
30
30
|
r.message.should be == "I am a failure."
|
31
31
|
end
|
32
32
|
end
|
@@ -100,6 +100,7 @@ describe FlexmlsApi do
|
|
100
100
|
subject do
|
101
101
|
class RequestTest
|
102
102
|
include FlexmlsApi::Request
|
103
|
+
attr_accessor *FlexmlsApi::Configuration::VALID_OPTION_KEYS
|
103
104
|
def initialize(session)
|
104
105
|
@session = session
|
105
106
|
end
|
@@ -138,25 +139,25 @@ describe FlexmlsApi do
|
|
138
139
|
it "should put to a service" do
|
139
140
|
# This is a hypothetical unsupported service action at this time
|
140
141
|
data = {"Contacts" => [{"DisplayName"=>"WLMCEWENS Contact","PrimaryEmail"=>"wlmcewen789@fbsdata.com"}]}
|
141
|
-
subject.put('/contacts/1000', data).should be
|
142
|
+
subject.put('/contacts/1000', data).should be(nil)
|
142
143
|
# No validation here, if no error is raised, everything is hunky dory
|
143
144
|
end
|
144
145
|
it "should delete from a service" do
|
145
146
|
# This is a hypothetical unsupported service action at this time
|
146
|
-
subject.delete('/contacts/1000').should be
|
147
|
+
subject.delete('/contacts/1000').should be(nil)
|
147
148
|
# No validation here, if no error is raised, everything is hunky dory
|
148
149
|
end
|
149
150
|
|
150
151
|
it "should give me BigDecimal results for large floating point numbers" do
|
151
|
-
MultiJson.default_engine.should eq
|
152
|
+
MultiJson.default_engine.should eq(:yajl)
|
152
153
|
result = subject.get('/listings/1000')[0]
|
153
|
-
result["StandardFields"]["BuildingAreaTotal"].class.should eq
|
154
|
+
result["StandardFields"]["BuildingAreaTotal"].class.should eq(Float)
|
154
155
|
pending("our JSON parser does not support large decimal types. Anyone feel like writing some c code?") do
|
155
|
-
result["StandardFields"]["BuildingAreaTotal"].class.should eq
|
156
|
+
result["StandardFields"]["BuildingAreaTotal"].class.should eq(BigDecimal)
|
156
157
|
number = BigDecimal.new(result["StandardFields"]["BuildingAreaTotal"].to_s)
|
157
|
-
number.to_s.should eq
|
158
|
+
number.to_s.should eq(BigDecimal.new("0.000000000000000000000000001").to_s)
|
158
159
|
number = BigDecimal.new(result["StandardFields"]["ListPrice"].to_s)
|
159
|
-
number.to_s.should eq
|
160
|
+
number.to_s.should eq(BigDecimal.new("9999999999999999999999999.99").to_s)
|
160
161
|
end
|
161
162
|
end
|
162
163
|
|
@@ -166,6 +167,7 @@ describe FlexmlsApi do
|
|
166
167
|
subject do
|
167
168
|
class RequestAuthTest
|
168
169
|
include FlexmlsApi::Request
|
170
|
+
attr_accessor *FlexmlsApi::Configuration::VALID_OPTION_KEYS
|
169
171
|
def authenticate()
|
170
172
|
@session ||= mock_session()
|
171
173
|
end
|
@@ -194,6 +196,7 @@ describe FlexmlsApi do
|
|
194
196
|
subject do
|
195
197
|
class RequestExpiredTest
|
196
198
|
include FlexmlsApi::Request
|
199
|
+
attr_accessor *FlexmlsApi::Configuration::VALID_OPTION_KEYS
|
197
200
|
def initialize(session)
|
198
201
|
@session = session
|
199
202
|
@reauthenticated = false
|
@@ -250,6 +253,7 @@ describe FlexmlsApi do
|
|
250
253
|
subject do
|
251
254
|
class RequestAlwaysExpiredJerkTest
|
252
255
|
include FlexmlsApi::Request
|
256
|
+
attr_accessor *FlexmlsApi::Configuration::VALID_OPTION_KEYS
|
253
257
|
def initialize()
|
254
258
|
@reauthenticated = 0
|
255
259
|
end
|
metadata
CHANGED
@@ -1,21 +1,22 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: flexmls_api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 31
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 3
|
9
|
-
-
|
10
|
-
version: 0.3.
|
9
|
+
- 6
|
10
|
+
version: 0.3.6
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Brandon Hornseth
|
14
|
+
- Wade McEwen
|
14
15
|
autorequire:
|
15
16
|
bindir: bin
|
16
17
|
cert_chain: []
|
17
18
|
|
18
|
-
date: 2011-03-
|
19
|
+
date: 2011-03-16 00:00:00 -05:00
|
19
20
|
default_executable:
|
20
21
|
dependencies:
|
21
22
|
- !ruby/object:Gem::Dependency
|
@@ -212,11 +213,13 @@ files:
|
|
212
213
|
- lib/flexmls_api/configuration.rb
|
213
214
|
- lib/flexmls_api/faraday.rb
|
214
215
|
- lib/flexmls_api/models.rb
|
216
|
+
- lib/flexmls_api/models/account.rb
|
215
217
|
- lib/flexmls_api/models/base.rb
|
216
218
|
- lib/flexmls_api/models/connect_prefs.rb
|
217
219
|
- lib/flexmls_api/models/contact.rb
|
218
220
|
- lib/flexmls_api/models/custom_fields.rb
|
219
221
|
- lib/flexmls_api/models/document.rb
|
222
|
+
- lib/flexmls_api/models/finders.rb
|
220
223
|
- lib/flexmls_api/models/idx_link.rb
|
221
224
|
- lib/flexmls_api/models/listing.rb
|
222
225
|
- lib/flexmls_api/models/market_statistics.rb
|
@@ -228,6 +231,7 @@ files:
|
|
228
231
|
- lib/flexmls_api/models/video.rb
|
229
232
|
- lib/flexmls_api/models/virtual_tour.rb
|
230
233
|
- lib/flexmls_api/paginate.rb
|
234
|
+
- lib/flexmls_api/primary_array.rb
|
231
235
|
- lib/flexmls_api/request.rb
|
232
236
|
- lib/flexmls_api/version.rb
|
233
237
|
- spec/fixtures/contacts.json
|
@@ -248,6 +252,7 @@ files:
|
|
248
252
|
- spec/unit/flexmls_api/authentication_spec.rb
|
249
253
|
- spec/unit/flexmls_api/configuration_spec.rb
|
250
254
|
- spec/unit/flexmls_api/faraday_spec.rb
|
255
|
+
- spec/unit/flexmls_api/models/account_spec.rb
|
251
256
|
- spec/unit/flexmls_api/models/base_spec.rb
|
252
257
|
- spec/unit/flexmls_api/models/connect_prefs_spec.rb
|
253
258
|
- spec/unit/flexmls_api/models/contact_spec.rb
|
@@ -260,6 +265,7 @@ files:
|
|
260
265
|
- spec/unit/flexmls_api/models/video_spec.rb
|
261
266
|
- spec/unit/flexmls_api/models/virtual_tour_spec.rb
|
262
267
|
- spec/unit/flexmls_api/paginate_spec.rb
|
268
|
+
- spec/unit/flexmls_api/primary_array_spec.rb
|
263
269
|
- spec/unit/flexmls_api/request_spec.rb
|
264
270
|
- spec/unit/flexmls_api_spec.rb
|
265
271
|
has_rdoc: true
|
@@ -302,6 +308,7 @@ test_files:
|
|
302
308
|
- spec/unit/flexmls_api/authentication_spec.rb
|
303
309
|
- spec/unit/flexmls_api/configuration_spec.rb
|
304
310
|
- spec/unit/flexmls_api/faraday_spec.rb
|
311
|
+
- spec/unit/flexmls_api/models/account_spec.rb
|
305
312
|
- spec/unit/flexmls_api/models/base_spec.rb
|
306
313
|
- spec/unit/flexmls_api/models/connect_prefs_spec.rb
|
307
314
|
- spec/unit/flexmls_api/models/contact_spec.rb
|
@@ -314,5 +321,6 @@ test_files:
|
|
314
321
|
- spec/unit/flexmls_api/models/video_spec.rb
|
315
322
|
- spec/unit/flexmls_api/models/virtual_tour_spec.rb
|
316
323
|
- spec/unit/flexmls_api/paginate_spec.rb
|
324
|
+
- spec/unit/flexmls_api/primary_array_spec.rb
|
317
325
|
- spec/unit/flexmls_api/request_spec.rb
|
318
326
|
- spec/unit/flexmls_api_spec.rb
|