flexmls_api 0.3.3 → 0.3.6
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.
- 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
|