mls 0.14.0 → 1.0.0
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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/Rakefile +6 -6
- data/lib/mls.rb +73 -427
- data/lib/mls/account.rb +15 -0
- data/lib/mls/address.rb +4 -0
- data/lib/mls/agency.rb +6 -0
- data/lib/mls/brokerage.rb +7 -0
- data/lib/mls/coworking_space.rb +5 -0
- data/lib/mls/floorplan.rb +11 -0
- data/lib/mls/flyer.rb +11 -0
- data/lib/mls/lease.rb +2 -0
- data/lib/mls/listing.rb +135 -0
- data/lib/mls/locality.rb +6 -0
- data/lib/mls/photo.rb +18 -0
- data/lib/mls/property.rb +24 -0
- data/lib/mls/region.rb +13 -0
- data/lib/mls/sale.rb +2 -0
- data/lib/mls/space.rb +3 -0
- data/lib/mls/sublease.rb +2 -0
- data/lib/mls/use.rb +25 -0
- data/mls.gemspec +11 -15
- data/test/mls/attribute_test.rb +55 -0
- data/test/mls/resource_test.rb +31 -0
- data/test/mls_test.rb +27 -0
- data/test/test_helper.rb +26 -27
- metadata +43 -75
- data/lib/mls/attribute.rb +0 -44
- data/lib/mls/attributes/array.rb +0 -11
- data/lib/mls/attributes/boolean.rb +0 -9
- data/lib/mls/attributes/datetime.rb +0 -25
- data/lib/mls/attributes/decimal.rb +0 -21
- data/lib/mls/attributes/fixnum.rb +0 -16
- data/lib/mls/attributes/hash.rb +0 -15
- data/lib/mls/attributes/string.rb +0 -15
- data/lib/mls/errors.rb +0 -29
- data/lib/mls/factories/account.rb +0 -34
- data/lib/mls/factories/address.rb +0 -16
- data/lib/mls/factories/listing.rb +0 -29
- data/lib/mls/factories_helper.rb +0 -7
- data/lib/mls/model.rb +0 -125
- data/lib/mls/models/account.rb +0 -174
- data/lib/mls/models/address.rb +0 -58
- data/lib/mls/models/brokerage.rb +0 -31
- data/lib/mls/models/floorplan.rb +0 -45
- data/lib/mls/models/flyer.rb +0 -45
- data/lib/mls/models/listing.rb +0 -394
- data/lib/mls/models/pdf.rb +0 -15
- data/lib/mls/models/photo.rb +0 -40
- data/lib/mls/models/property.rb +0 -114
- data/lib/mls/models/region.rb +0 -56
- data/lib/mls/models/tour.rb +0 -54
- data/lib/mls/models/video.rb +0 -18
- data/lib/mls/parser.rb +0 -74
- data/lib/mls/resource.rb +0 -99
- data/lib/rdoc/generator/template/42floors/_context.rhtml +0 -209
- data/lib/rdoc/generator/template/42floors/_head.rhtml +0 -7
- data/lib/rdoc/generator/template/42floors/class.rhtml +0 -39
- data/lib/rdoc/generator/template/42floors/file.rhtml +0 -35
- data/lib/rdoc/generator/template/42floors/index.rhtml +0 -13
- data/lib/rdoc/generator/template/42floors/resources/apple-touch-icon.png +0 -0
- data/lib/rdoc/generator/template/42floors/resources/css/github.css +0 -129
- data/lib/rdoc/generator/template/42floors/resources/css/main.css +0 -339
- data/lib/rdoc/generator/template/42floors/resources/css/panel.css +0 -389
- data/lib/rdoc/generator/template/42floors/resources/css/reset.css +0 -48
- data/lib/rdoc/generator/template/42floors/resources/favicon.ico +0 -0
- data/lib/rdoc/generator/template/42floors/resources/i/arrows.png +0 -0
- data/lib/rdoc/generator/template/42floors/resources/i/results_bg.png +0 -0
- data/lib/rdoc/generator/template/42floors/resources/i/tree_bg.png +0 -0
- data/lib/rdoc/generator/template/42floors/resources/js/highlight.pack.js +0 -1
- data/lib/rdoc/generator/template/42floors/resources/js/jquery-1.3.2.min.js +0 -19
- data/lib/rdoc/generator/template/42floors/resources/js/jquery-effect.js +0 -593
- data/lib/rdoc/generator/template/42floors/resources/js/main.js +0 -20
- data/lib/rdoc/generator/template/42floors/resources/js/searchdoc.js +0 -442
- data/lib/rdoc/generator/template/42floors/resources/panel/index.html +0 -73
- data/lib/rdoc/generator/template/42floors/se_index.rhtml +0 -8
- data/test/units/properties/test_boolean.rb +0 -4
- data/test/units/test_errors.rb +0 -32
- data/test/units/test_mls.rb +0 -294
- data/test/units/test_property.rb +0 -35
data/lib/mls/attributes/hash.rb
DELETED
data/lib/mls/errors.rb
DELETED
@@ -1,29 +0,0 @@
|
|
1
|
-
class MLS::Exception < Exception
|
2
|
-
end
|
3
|
-
|
4
|
-
class MLS::Exception::UnexpectedResponse < MLS::Exception
|
5
|
-
end
|
6
|
-
|
7
|
-
class MLS::Exception::BadRequest < MLS::Exception
|
8
|
-
end
|
9
|
-
|
10
|
-
class MLS::Exception::Unauthorized < MLS::Exception
|
11
|
-
end
|
12
|
-
|
13
|
-
class MLS::Exception::NotFound < MLS::Exception
|
14
|
-
end
|
15
|
-
|
16
|
-
class MLS::Exception::Gone < MLS::Exception
|
17
|
-
end
|
18
|
-
|
19
|
-
class MLS::Exception::MovedPermanently < MLS::Exception
|
20
|
-
end
|
21
|
-
|
22
|
-
class MLS::Exception::ApiVersionUnsupported < MLS::Exception
|
23
|
-
end
|
24
|
-
|
25
|
-
class MLS::Exception::RecordInvalid < MLS::Exception
|
26
|
-
end
|
27
|
-
|
28
|
-
class MLS::Exception::ServiceUnavailable < MLS::Exception
|
29
|
-
end
|
@@ -1,34 +0,0 @@
|
|
1
|
-
FactoryGirl.define do
|
2
|
-
factory :account, :class => MLS::Account do
|
3
|
-
name { Faker::Name.name }
|
4
|
-
email { Faker::Internet.email }
|
5
|
-
password { 'test' }
|
6
|
-
password_confirmation 'test'
|
7
|
-
end
|
8
|
-
|
9
|
-
factory :agent, :class => MLS::Account do
|
10
|
-
phone { Faker::PhoneNumber.phone_number }
|
11
|
-
company { Faker::Company.name }
|
12
|
-
license '12123123123'
|
13
|
-
name { Faker::Name.name }
|
14
|
-
email { Faker::Internet.email }
|
15
|
-
password 'test'
|
16
|
-
password_confirmation 'test'
|
17
|
-
type 'Agent'
|
18
|
-
end
|
19
|
-
|
20
|
-
factory :admin, :class => MLS::Account do
|
21
|
-
name { Faker::Name.name }
|
22
|
-
email { Faker::Internet.email }
|
23
|
-
type {'Admin'}
|
24
|
-
password { 'admin_test' }
|
25
|
-
password_confirmation 'admin_test'
|
26
|
-
end
|
27
|
-
|
28
|
-
factory :ghost_account, :class => MLS::Account do
|
29
|
-
name { Faker::Name.name }
|
30
|
-
email { Faker::Internet.email }
|
31
|
-
password_required { false }
|
32
|
-
end
|
33
|
-
|
34
|
-
end
|
@@ -1,16 +0,0 @@
|
|
1
|
-
FactoryGirl.define do
|
2
|
-
factory :address, :class => MLS::Address do
|
3
|
-
street_number { Kernel.rand(1000).to_s }
|
4
|
-
street { Faker::Address.street_name }
|
5
|
-
neighborhood { Faker::Name.name }
|
6
|
-
city { Faker::Address.city }
|
7
|
-
county { |p| p.city }
|
8
|
-
state { Faker::Address.state_abbr }
|
9
|
-
country 'US'
|
10
|
-
postal_code { Faker::Address.zip_code }
|
11
|
-
formatted_address { |p| "#{p.street_number} #{p.street}, #{p.city}, #{p.state}, #{p.postal_code}" }
|
12
|
-
latitude { Kernel.rand((-90.0)..(90.0)) }
|
13
|
-
longitude { Kernel.rand((-180.0)..(180.0)) }
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
@@ -1,29 +0,0 @@
|
|
1
|
-
FactoryGirl.define do
|
2
|
-
factory :listing, :class => MLS::Listing do
|
3
|
-
before(:create) { |l|
|
4
|
-
MLS_GEM_CACHE['auth_cookie'] = MLS.auth_cookie
|
5
|
-
MLS.auth_cookie = l.account.auth_cookie
|
6
|
-
}
|
7
|
-
after(:create) { |l|
|
8
|
-
MLS.auth_cookie = MLS_GEM_CACHE['auth_cookie']
|
9
|
-
}
|
10
|
-
|
11
|
-
association :account
|
12
|
-
association :address, :strategy => :build
|
13
|
-
|
14
|
-
agents { [FactoryGirl.attributes_for(:agent)] }
|
15
|
-
|
16
|
-
use 'Office'
|
17
|
-
size { Kernel.rand(3000..900000) }
|
18
|
-
maximum_contiguous_size { Kernel.rand(3000..900000) }
|
19
|
-
minimum_divisible_size { Kernel.rand(3000..900000) }
|
20
|
-
type 'lease'
|
21
|
-
#lease_terms { ::MLS::Listing::LEASE_TERMS.sample }
|
22
|
-
space_type 'unit'
|
23
|
-
rate { rand(15..300) }
|
24
|
-
available_on { Time.now + (20 + rand(0..360).to_i).days }
|
25
|
-
sublease_expiration { |l| l.sublease? ? (l.available_on + (30 + Kernel.rand(10..360)).days) : nil }
|
26
|
-
name { |l| l.type == 'coworking_space' ? Faker::Name.name : nil }
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
data/lib/mls/factories_helper.rb
DELETED
data/lib/mls/model.rb
DELETED
@@ -1,125 +0,0 @@
|
|
1
|
-
module MLS::Model
|
2
|
-
|
3
|
-
def self.extended(model) #:nodoc:
|
4
|
-
model.instance_variable_set(:@attributes, {})
|
5
|
-
model.instance_variable_set(:@associations, {})
|
6
|
-
end
|
7
|
-
|
8
|
-
# Creates an object and saves it to the MLS. The resulting object is returned
|
9
|
-
# whether or no the object was saved successfully to the MLS or not.
|
10
|
-
#
|
11
|
-
# ==== Examples
|
12
|
-
# #!ruby
|
13
|
-
# # Create a single new object
|
14
|
-
# User.create(:first_name => 'Jamie')
|
15
|
-
#
|
16
|
-
# # Create a single object and pass it into a block to set other attributes.
|
17
|
-
# User.create(:first_name => 'Jamie') do |u|
|
18
|
-
# u.is_admin = false
|
19
|
-
# end
|
20
|
-
def create(attributes={}, &block) # TODO: testme
|
21
|
-
model = self.new(attributes)
|
22
|
-
yield(model) if block_given?
|
23
|
-
model.save
|
24
|
-
model
|
25
|
-
end
|
26
|
-
|
27
|
-
# Attributes ===================================================================================================
|
28
|
-
|
29
|
-
def attribute(name, type, options = {})
|
30
|
-
klass = MLS::Attribute.determine_class(type)
|
31
|
-
raise NotImplementedError, "#{type} is not supported" unless klass
|
32
|
-
|
33
|
-
attribute = klass.new(name, options)
|
34
|
-
@attributes[attribute.name] = attribute
|
35
|
-
@attributes_excluded_from_comparison = []
|
36
|
-
|
37
|
-
create_reader_for(attribute)
|
38
|
-
create_writer_for(attribute)
|
39
|
-
end
|
40
|
-
|
41
|
-
def exclude_from_comparison(*attributes)
|
42
|
-
@attributes_excluded_from_comparison |= attributes
|
43
|
-
end
|
44
|
-
|
45
|
-
def attributes_excluded_from_comparison
|
46
|
-
@attributes_excluded_from_comparison
|
47
|
-
end
|
48
|
-
|
49
|
-
def attributes
|
50
|
-
@attributes
|
51
|
-
end
|
52
|
-
|
53
|
-
def attribute_module
|
54
|
-
@attribute_module ||= begin
|
55
|
-
mod = Module.new
|
56
|
-
class_eval do
|
57
|
-
include mod
|
58
|
-
end
|
59
|
-
mod
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
def create_reader_for(attribute)
|
64
|
-
reader_name = attribute.name.to_s
|
65
|
-
boolean_reader_name = "#{reader_name}?"
|
66
|
-
reader_visibility = attribute.reader_visibility
|
67
|
-
instance_variable_name = attribute.instance_variable_name
|
68
|
-
|
69
|
-
attribute_module.module_eval <<-RUBY, __FILE__, __LINE__ + 1
|
70
|
-
#{reader_visibility}
|
71
|
-
def #{reader_name}
|
72
|
-
return #{instance_variable_name} if defined?(#{instance_variable_name})
|
73
|
-
attribute = attributes[:#{reader_name}]
|
74
|
-
#{instance_variable_name} = attribute ? attribute.default : nil
|
75
|
-
end
|
76
|
-
RUBY
|
77
|
-
|
78
|
-
if attribute.kind_of?(MLS::Attribute::Boolean)
|
79
|
-
attribute_module.module_eval <<-RUBY, __FILE__, __LINE__ + 1
|
80
|
-
#{reader_visibility}
|
81
|
-
def #{boolean_reader_name}
|
82
|
-
#{reader_name}
|
83
|
-
end
|
84
|
-
RUBY
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
def create_writer_for(attribute)
|
89
|
-
name = attribute.name
|
90
|
-
writer_name = "#{name}="
|
91
|
-
writer_visibility = attribute.writer_visibility
|
92
|
-
instance_variable_name = attribute.instance_variable_name
|
93
|
-
|
94
|
-
attribute_module.module_eval <<-RUBY, __FILE__, __LINE__ + 1
|
95
|
-
#{writer_visibility}
|
96
|
-
def #{writer_name}(value)
|
97
|
-
attribute = self.class.attributes[:#{name}]
|
98
|
-
#{instance_variable_name} = attribute.load(value)
|
99
|
-
end
|
100
|
-
RUBY
|
101
|
-
end
|
102
|
-
|
103
|
-
#== for rails form stuff
|
104
|
-
def model_name
|
105
|
-
self
|
106
|
-
end
|
107
|
-
|
108
|
-
def param_key
|
109
|
-
root_element.to_s
|
110
|
-
end
|
111
|
-
|
112
|
-
# used for parser
|
113
|
-
def root_element_string
|
114
|
-
ActiveSupport::Inflector.demodulize(self).underscore
|
115
|
-
end
|
116
|
-
|
117
|
-
def root_element
|
118
|
-
@root_element ||= root_element_string.to_sym
|
119
|
-
end
|
120
|
-
|
121
|
-
def collection_root_element
|
122
|
-
@collection_root_element ||= root_element_string.pluralize.to_sym
|
123
|
-
end
|
124
|
-
|
125
|
-
end
|
data/lib/mls/models/account.rb
DELETED
@@ -1,174 +0,0 @@
|
|
1
|
-
class MLS::Account < MLS::Resource
|
2
|
-
|
3
|
-
attribute :id, Fixnum, :serialize => :if_present
|
4
|
-
attribute :type, String, :default => 'Account'
|
5
|
-
attribute :name, String, :serialize => :if_present
|
6
|
-
attribute :title, String, :serialize => :if_present
|
7
|
-
attribute :email, String, :serialize => :if_present
|
8
|
-
attribute :password, String, :serialize => :if_present
|
9
|
-
attribute :password_confirmation, String, :serialize => :if_present
|
10
|
-
attribute :perishable_token, String, :serialize => false
|
11
|
-
attribute :perishable_token_set_at, String, :serialize => false
|
12
|
-
attribute :ghost, Boolean, :serialize => false, :default => false
|
13
|
-
|
14
|
-
attribute :phone, String, :serialize => :if_present
|
15
|
-
attribute :company, String, :serialize => :if_present
|
16
|
-
attribute :license, String, :serialize => :if_present
|
17
|
-
attribute :linkedin, String, :serialize => :if_present
|
18
|
-
attribute :twitter, String, :serialize => :if_present
|
19
|
-
attribute :facebook, String, :serialize => :if_present
|
20
|
-
attribute :web, String, :serialize => :if_present
|
21
|
-
attribute :direct_phone, String, :serialize => :if_present
|
22
|
-
attribute :direct_email, String, :serialize => :if_present
|
23
|
-
|
24
|
-
attribute :city, String, :serialize => :if_present
|
25
|
-
attribute :state, String, :serialize => :if_present
|
26
|
-
attribute :country, String, :serialize => :if_present
|
27
|
-
|
28
|
-
attribute :created_at, DateTime, :serialize => :false
|
29
|
-
attribute :updated_at, DateTime, :serialize => :false
|
30
|
-
|
31
|
-
attribute :email_token, String, :serialize => false
|
32
|
-
attribute :start_hours_of_operation, Fixnum, :serialize => :if_present
|
33
|
-
attribute :end_hours_of_operation, Fixnum, :serialize => :if_present
|
34
|
-
attribute :days_of_operation, String, :serialize => :if_present
|
35
|
-
attribute :timezone, String, :serialize => :if_present
|
36
|
-
attribute :lead_status, String, :serialize => :if_present
|
37
|
-
attribute :buyer_id, Fixnum, :serialize => :if_present
|
38
|
-
|
39
|
-
exclude_from_comparison :password, :password_confirmation
|
40
|
-
|
41
|
-
attr_accessor :password_required, :brokerage
|
42
|
-
|
43
|
-
attr_writer :favorites
|
44
|
-
|
45
|
-
def update
|
46
|
-
raise "cannot update account without id" unless id
|
47
|
-
MLS.put("/accounts/#{id}", { :account => to_hash}, 400) do |response, code|
|
48
|
-
MLS::Account::Parser.update(self, response.body)
|
49
|
-
code == 200
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
# Save the Account to the MLS. @errors will be set on the account if there
|
54
|
-
# are any errors. @persisted will also be set to +true+ if the Account was
|
55
|
-
# succesfully created
|
56
|
-
def create
|
57
|
-
MLS.post('/accounts', {:account => to_hash}, 400) do |response, code|
|
58
|
-
raise MLS::Exception::UnexpectedResponse if ![201, 400].include?(code)
|
59
|
-
MLS::Account::Parser.update(self, response.body)
|
60
|
-
@persisted = true
|
61
|
-
code == 201
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
def display_name
|
66
|
-
name || email
|
67
|
-
end
|
68
|
-
|
69
|
-
def agent?
|
70
|
-
type == 'Agent'
|
71
|
-
end
|
72
|
-
|
73
|
-
def favorites
|
74
|
-
return @favorites if @favorites
|
75
|
-
response = MLS.get('/account/favorites')
|
76
|
-
@favorites = MLS::Listing::Parser.parse_collection(response.body, {:collection_root_element => :favorites})
|
77
|
-
end
|
78
|
-
|
79
|
-
def agent_profile
|
80
|
-
@agent_profile ||= MLS.agent_profile id
|
81
|
-
end
|
82
|
-
|
83
|
-
def favorited?(listing)
|
84
|
-
favorites.include?(listing)
|
85
|
-
end
|
86
|
-
|
87
|
-
def favorite(listing) # TODO: test me, i don't work on failures
|
88
|
-
params_hash = {:id => listing.is_a?(MLS::Listing) ? listing.id : listing }
|
89
|
-
MLS.post('/account/favorites', params_hash) do |response, code|
|
90
|
-
@favorites = nil
|
91
|
-
true
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
def unfavorite(listing_id) # TODO: test me, i don't work on failures
|
96
|
-
listing_id = listing_id.is_a?(MLS::Listing) ? listing_id.id : listing_id
|
97
|
-
MLS.delete("/account/favorites/#{listing_id}") do |response, code|
|
98
|
-
@favorites = nil
|
99
|
-
true
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
def to_hash
|
104
|
-
hash = super
|
105
|
-
hash[:password_required] = password_required unless password_required.nil?
|
106
|
-
hash
|
107
|
-
end
|
108
|
-
|
109
|
-
class << self
|
110
|
-
|
111
|
-
def current
|
112
|
-
response = MLS.get('/account')
|
113
|
-
MLS::Account::Parser.parse(response.body)
|
114
|
-
end
|
115
|
-
|
116
|
-
# Authenticate and Account via <tt>email</tt> and <tt>password</tt>. Returns
|
117
|
-
# the <tt>Account</tt> object if successfully authenticated. Returns <tt>nil</tt>
|
118
|
-
# if the account could not be found, password was incorrect, or the account
|
119
|
-
# was revoked
|
120
|
-
#
|
121
|
-
# ==== Examples
|
122
|
-
# #!ruby
|
123
|
-
# Account.authenticate(:email => 'jon@does.net', :password => 'opensesame') # => #<Account>
|
124
|
-
#
|
125
|
-
# Account.authenticate('jon@does.net', 'opensesame') # => #<Account>
|
126
|
-
#
|
127
|
-
# Account.authenticate('jon@does.net', 'wrong') # => nil
|
128
|
-
def authenticate(attrs_or_email, password=nil)
|
129
|
-
email = attrs_or_email.is_a?(Hash) ? attrs_or_email[:email] : attrs_or_email
|
130
|
-
password = attrs_or_email.is_a?(Hash) ? attrs_or_email[:password] : password
|
131
|
-
response = MLS.post('/login', {:email => email, :password => password})
|
132
|
-
account = MLS::Account::Parser.parse(response.body)
|
133
|
-
account
|
134
|
-
rescue MLS::Exception::Unauthorized => response
|
135
|
-
nil
|
136
|
-
end
|
137
|
-
|
138
|
-
# URL is currently required to not have any query params in it
|
139
|
-
def reset_password!(email, url)
|
140
|
-
MLS.post('/account/password', {:email => email, :url => url}, 400, 404) do |response, code|
|
141
|
-
code == 204
|
142
|
-
end
|
143
|
-
end
|
144
|
-
|
145
|
-
def update_password!(token, password, password_confirmation)
|
146
|
-
MLS.put('/account/password', {:token => token, :password => password, :password_confirmation => password_confirmation}, 400) do |response, code|
|
147
|
-
MLS::Account::Parser.parse(response.body)
|
148
|
-
end
|
149
|
-
end
|
150
|
-
|
151
|
-
def find(id, includes=[])
|
152
|
-
response = MLS.get("/accounts/#{id}", :include => includes)
|
153
|
-
MLS::Account::Parser.parse(response.body)
|
154
|
-
end
|
155
|
-
|
156
|
-
def where(terms)
|
157
|
-
response = MLS.get('/accounts', :where => terms)
|
158
|
-
MLS::Account::Parser.parse_collection(response.body)
|
159
|
-
end
|
160
|
-
|
161
|
-
end
|
162
|
-
|
163
|
-
end
|
164
|
-
|
165
|
-
class MLS::Account::Parser < MLS::Parser
|
166
|
-
|
167
|
-
def favorites=(favorites)
|
168
|
-
@object.favorites = favorites.map {|a| MLS::Listing::Parser.build(a) }
|
169
|
-
end
|
170
|
-
|
171
|
-
def brokerage=(brokerage)
|
172
|
-
@object.brokerage = MLS::Brokerage::Parser.build(brokerage)
|
173
|
-
end
|
174
|
-
end
|