mls 0.11.3 → 0.12.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/lib/mls.rb +46 -46
  3. data/lib/mls/{property.rb → attribute.rb} +2 -2
  4. data/lib/mls/{properties → attributes}/array.rb +1 -1
  5. data/lib/mls/{properties → attributes}/boolean.rb +1 -1
  6. data/lib/mls/{properties → attributes}/datetime.rb +1 -1
  7. data/lib/mls/{properties → attributes}/decimal.rb +1 -1
  8. data/lib/mls/{properties → attributes}/fixnum.rb +1 -1
  9. data/lib/mls/{properties → attributes}/hash.rb +1 -1
  10. data/lib/mls/{properties → attributes}/string.rb +1 -1
  11. data/lib/mls/factories/listing.rb +3 -3
  12. data/lib/mls/model.rb +33 -33
  13. data/lib/mls/models/account.rb +55 -46
  14. data/lib/mls/models/address.rb +18 -117
  15. data/lib/mls/models/brokerage.rb +6 -6
  16. data/lib/mls/models/floorplan.rb +5 -5
  17. data/lib/mls/models/flyer.rb +5 -5
  18. data/lib/mls/models/listing.rb +80 -76
  19. data/lib/mls/models/pdf.rb +4 -4
  20. data/lib/mls/models/photo.rb +10 -10
  21. data/lib/mls/models/property.rb +113 -0
  22. data/lib/mls/models/region.rb +14 -14
  23. data/lib/mls/models/tour.rb +10 -10
  24. data/lib/mls/models/video.rb +7 -7
  25. data/lib/mls/parser.rb +1 -1
  26. data/lib/mls/resource.rb +15 -15
  27. data/lib/rdoc/generator/template/42floors/resources/css/github.css +1 -1
  28. data/lib/rdoc/generator/template/42floors/resources/js/highlight.pack.js +1 -1
  29. data/lib/rdoc/generator/template/42floors/resources/js/jquery-1.3.2.min.js +1 -1
  30. data/lib/rdoc/generator/template/42floors/resources/js/jquery-effect.js +6 -6
  31. data/mls.gemspec +1 -1
  32. data/test/test_helper.rb +1 -1
  33. data/test/units/models/test_address.rb +4 -4
  34. data/test/units/models/test_contact.rb +1 -1
  35. data/test/units/models/test_listing.rb +4 -4
  36. data/test/units/test_mls.rb +60 -60
  37. data/test/units/test_model.rb +3 -3
  38. data/test/units/test_property.rb +18 -18
  39. data/test/units/test_resource.rb +1 -1
  40. metadata +12 -11
@@ -1,43 +1,45 @@
1
1
  class MLS::Account < MLS::Resource
2
-
3
- property :id, Fixnum, :serialize => :if_present
4
- property :type, String, :default => 'Account'
5
- property :name, String, :serialize => :if_present
6
- property :title, String, :serialize => :if_present
7
- property :email, String, :serialize => :if_present
8
- property :password, String, :serialize => :if_present
9
- property :password_confirmation, String, :serialize => :if_present
10
- property :perishable_token, String, :serialize => false
11
- property :perishable_token_set_at, String, :serialize => false
12
- property :ghost, Boolean, :serialize => false, :default => false
13
-
14
- property :phone, String, :serialize => :if_present
15
- property :company, String, :serialize => :if_present
16
- property :license, String, :serialize => :if_present
17
- property :linkedin, String, :serialize => :if_present
18
- property :twitter, String, :serialize => :if_present
19
- property :facebook, String, :serialize => :if_present
20
- property :web, String, :serialize => :if_present
21
-
22
- property :city, String, :serialize => :if_present
23
- property :state, String, :serialize => :if_present
24
- property :country, String, :serialize => :if_present
25
-
26
- property :created_at, DateTime, :serialize => :false
27
- property :updated_at, DateTime, :serialize => :false
28
-
29
- property :email_token, String, :serialize => false
30
- property :auth_key, String, :serialize => false
31
- property :start_hours_of_operation, Fixnum, :serialize => :if_present
32
- property :end_hours_of_operation, Fixnum, :serialize => :if_present
33
- property :days_of_operation, String, :serialize => :if_present
34
- property :timezone, String, :serialize => :if_present
35
- property :lead_status, String, :serialize => :if_present
36
- property :buyer_id, Fixnum, :serialize => :if_present
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 :auth_cookie, String, :serialize => false
33
+ attribute :start_hours_of_operation, Fixnum, :serialize => :if_present
34
+ attribute :end_hours_of_operation, Fixnum, :serialize => :if_present
35
+ attribute :days_of_operation, String, :serialize => :if_present
36
+ attribute :timezone, String, :serialize => :if_present
37
+ attribute :lead_status, String, :serialize => :if_present
38
+ attribute :buyer_id, Fixnum, :serialize => :if_present
37
39
 
38
40
  exclude_from_comparison :password, :password_confirmation
39
41
 
40
- attr_accessor :password_required
42
+ attr_accessor :password_required, :brokerage
41
43
 
42
44
  attr_writer :favorites
43
45
 
@@ -47,7 +49,7 @@ class MLS::Account < MLS::Resource
47
49
  code == 200
48
50
  end
49
51
  end
50
-
52
+
51
53
  # Save the Account to the MLS. @errors will be set on the account if there
52
54
  # are any errors. @persisted will also be set to +true+ if the Account was
53
55
  # succesfully created
@@ -81,7 +83,7 @@ class MLS::Account < MLS::Resource
81
83
  def favorited?(listing)
82
84
  favorites.include?(listing)
83
85
  end
84
-
86
+
85
87
  def favorite(listing) # TODO: test me, i don't work on failures
86
88
  params_hash = {:id => listing.is_a?(MLS::Listing) ? listing.id : listing }
87
89
  MLS.post('/account/favorites', params_hash) do |response, code|
@@ -103,14 +105,14 @@ class MLS::Account < MLS::Resource
103
105
  hash[:password_required] = password_required unless password_required.nil?
104
106
  hash
105
107
  end
106
-
108
+
107
109
  class << self
108
110
 
109
111
  def current
110
112
  response = MLS.get('/account')
111
113
  MLS::Account::Parser.parse(response.body)
112
114
  end
113
-
115
+
114
116
  # Authenticate and Account via <tt>email</tt> and <tt>password</tt>. Returns
115
117
  # the <tt>Account</tt> object if successfully authenticated. Returns <tt>nil</tt>
116
118
  # if the account could not be found, password was incorrect, or the account
@@ -119,16 +121,20 @@ class MLS::Account < MLS::Resource
119
121
  # ==== Examples
120
122
  # #!ruby
121
123
  # Account.authenticate(:email => 'jon@does.net', :password => 'opensesame') # => #<Account>
122
- #
124
+ #
123
125
  # Account.authenticate('jon@does.net', 'opensesame') # => #<Account>
124
126
  #
125
127
  # Account.authenticate('jon@does.net', 'wrong') # => nil
126
128
  def authenticate(attrs_or_email, password=nil)
127
129
  email = attrs_or_email.is_a?(Hash) ? attrs_or_email[:email] : attrs_or_email
128
130
  password = attrs_or_email.is_a?(Hash) ? attrs_or_email[:password] : password
129
-
130
- response = MLS.get('/account', {:email => email, :password => password})
131
- MLS::Account::Parser.parse(response.body)
131
+
132
+ response = MLS.post('/login', {:email => email, :password => password})
133
+ MLS.auth_cookie = response['set-cookie']
134
+
135
+ account = MLS::Account::Parser.parse(response.body)
136
+ account.auth_cookie = MLS.auth_cookie
137
+ account
132
138
  rescue MLS::Exception::Unauthorized => response
133
139
  nil
134
140
  end
@@ -151,12 +157,12 @@ class MLS::Account < MLS::Resource
151
157
  end
152
158
 
153
159
  def find(id)
154
- response = MLS.get("/account/find", :id => id)
160
+ response = MLS.get("/account/find", :id => id)
155
161
  MLS::Account::Parser.parse(response.body)
156
162
  end
157
163
 
158
164
  end
159
-
165
+
160
166
  end
161
167
 
162
168
  class MLS::Account::Parser < MLS::Parser
@@ -165,4 +171,7 @@ class MLS::Account::Parser < MLS::Parser
165
171
  @object.favorites = favorites.map {|a| MLS::Listing::Parser.build(a) }
166
172
  end
167
173
 
174
+ def brokerage=(brokerage)
175
+ @object.brokerage = MLS::Brokerage::Parser.build(brokerage)
176
+ end
168
177
  end
@@ -1,65 +1,21 @@
1
1
  class MLS::Address < MLS::Resource
2
2
 
3
- property :id, Fixnum, :serialize => :false
4
- property :name, String, :serialize => :false
5
- property :slug, String, :serialize => :false
3
+ attribute :id, Fixnum, :serialize => :false
4
+ attribute :property_id, Fixnum, :serialize => :false
5
+ attribute :slug, String, :serialize => :false
6
6
 
7
- property :latitude, Decimal
8
- property :longitude, Decimal
7
+ attribute :formatted_address, String
8
+ attribute :street_number, String
9
+ attribute :street, String
10
+ attribute :neighborhood, String
11
+ attribute :city, String
12
+ attribute :county, String
13
+ attribute :state, String
14
+ attribute :country, String
15
+ attribute :postal_code, String
9
16
 
10
- property :formatted_address, String
11
- property :street_number, String
12
- property :street, String
13
- property :neighborhood, String
14
- property :city, String
15
- property :county, String
16
- property :state, String
17
- property :country, String
18
- property :postal_code, String
19
- property :min_rate_per_sqft_per_year, Decimal, :serialize => :false
20
- property :max_rate_per_sqft_per_year, Decimal, :serialize => :false
21
- property :max_size, Fixnum, :serialize => :false
22
- property :min_size, Fixnum, :serialize => :false
23
- property :description, String
24
- property :year_built, Fixnum
25
- property :size, Fixnum
26
- property :floors, Fixnum
27
-
28
- property :amenities, Hash
29
-
30
- property :leed_certification, String
17
+ attr_accessor :property
31
18
 
32
- # Counter caches
33
- property :listings_count, Fixnum, :serialize => :false
34
- property :leased_listings_count, Fixnum, :serialize => :false
35
- property :hidden_listings_count, Fixnum, :serialize => :false
36
- property :import_listings_count, Fixnum, :serialize => :false
37
- property :active_listings_count, Fixnum, :serialize => :false
38
-
39
- property :avatar_digest, String, :serialize => false
40
-
41
- property :listings_latest_created_at, DateTime, :serialize => :false
42
-
43
- attr_accessor :listings, :listing_types, :photos, :videos
44
-
45
- # should include an optional use address or no_image image
46
- def avatar(size='100x200#', protocol='http')
47
- params = {
48
- :size => size,
49
- :format => 'png',
50
- :sensor => false,
51
- :location => [formatted_address],
52
- :fov => 120
53
- }
54
-
55
- if avatar_digest
56
- "#{protocol}://#{MLS.image_host}/#{avatar_digest}.jpg?s=#{URI.escape(size)}"
57
- else
58
- params[:size] = params[:size].match(/\d+x\d+/)[0]
59
- "#{protocol}://maps.googleapis.com/maps/api/streetview?" + params.map{|k,v| k.to_s + '=' + URI.escape(v.to_s) }.join('&')
60
- end
61
- end
62
-
63
19
  def save
64
20
  MLS.put("/addresses/#{id}", {:address => to_hash}, 400) do |response, code|
65
21
  if code == 200 || code == 400
@@ -71,45 +27,11 @@ class MLS::Address < MLS::Resource
71
27
  end
72
28
  end
73
29
 
74
- def to_hash
75
- hash = super
76
- hash[:photo_ids] = photos.map(&:id) if photos
77
- hash[:videos_attributes] = videos.map(&:to_hash) unless videos.blank?
78
- hash
79
- end
80
-
81
30
  def to_param
82
- [state, city, "#{street_number} #{street}"].map(&:parameterize).join('/')
83
- end
84
-
85
- def url
86
- if defined? Rails
87
- case Rails.env
88
- when "production"
89
- host = "42floors.com"
90
- when "staging"
91
- host = "staging.42floors.com"
92
- when "development","test"
93
- host = "spire.dev"
94
- end
95
- else
96
- host = "42floors.com"
97
- end
98
- "http://#{host}/#{slug}"
99
- end
100
-
101
- def find_listings(space_available, floor, unit)
102
- response = MLS.get("/addresses/#{id}/find_listings",
103
- :floor => floor, :unit => unit, :space_available => space_available)
104
- MLS::Listing::Parser.parse_collection(response.body)
31
+ slug
105
32
  end
106
33
 
107
34
  class << self
108
-
109
- def query(q)
110
- response = MLS.get('/addresses/query', :query => q)
111
- MLS::Address::Parser.parse_collection(response.body)
112
- end
113
35
 
114
36
  def find(id)
115
37
  response = MLS.get("/addresses/#{id}")
@@ -122,36 +44,15 @@ class MLS::Address < MLS::Resource
122
44
  MLS::Address::Parser.parse_collection(response.body)
123
45
  end
124
46
 
125
- def amenities
126
- @amenities ||= Yajl::Parser.new(:symbolize_keys => true).parse(MLS.get('/addresses/amenities').body)
127
- end
128
-
129
47
  end
130
48
 
131
49
  end
132
50
 
133
51
 
134
52
  class MLS::Address::Parser < MLS::Parser
135
-
136
- def listings=(listings)
137
- @object.listings = listings.map { |data|
138
- listing = MLS::Listing::Parser.build(data)
139
- listing.address = @object
140
- listing
141
- }
142
- end
143
-
144
- def listing_types=(listing_types)
145
- @object.listing_types = listing_types
146
- end
147
-
148
- def photos=(photos)
149
- @object.photos = photos.map {|p| MLS::Photo::Parser.build(p)}
150
- end
151
-
152
- def videos=(videos)
153
- @object.videos = videos.map do |video|
154
- MLS::Video::Parser.build(video)
155
- end
53
+
54
+ def property=(property)
55
+ @object.property = MLS::Property::Parser.build(property)
156
56
  end
57
+
157
58
  end
@@ -1,11 +1,11 @@
1
1
  class MLS::Brokerage < MLS::Resource
2
2
 
3
- property :id, Fixnum, :serialize => :if_present
4
- property :name, String, :serialize => :if_present
5
- property :admin_id, Fixnum, :serialize => :if_present
6
- property :slug, String, :serialize => false
7
- property :palette, Hash, :serialize => :if_present
8
- property :avatar_digest, String, :serialize => false
3
+ attribute :id, Fixnum, :serialize => :if_present
4
+ attribute :name, String, :serialize => :if_present
5
+ attribute :admin_id, Fixnum, :serialize => :if_present
6
+ attribute :slug, String, :serialize => false
7
+ attribute :palette, Hash, :serialize => :if_present
8
+ attribute :avatar_digest, String, :serialize => false
9
9
 
10
10
  class << self
11
11
 
@@ -2,11 +2,11 @@ require 'restclient'
2
2
 
3
3
  class MLS::Floorplan < MLS::Resource
4
4
 
5
- property :id, Fixnum
6
- property :digest, String
7
- property :avatar_digest, String
8
- property :file_name, String
9
- property :file_size, Fixnum
5
+ attribute :id, Fixnum
6
+ attribute :digest, String
7
+ attribute :avatar_digest, String
8
+ attribute :file_name, String
9
+ attribute :file_size, Fixnum
10
10
 
11
11
  def url(protocol='http')
12
12
  "#{protocol}://#{MLS.asset_host}/floorplans/#{digest}/compressed/#{file_name}"
@@ -2,11 +2,11 @@ require 'restclient'
2
2
 
3
3
  class MLS::Flyer < MLS::Resource
4
4
 
5
- property :id, Fixnum
6
- property :digest, String
7
- property :avatar_digest, String
8
- property :file_name, String
9
- property :file_size, Fixnum
5
+ attribute :id, Fixnum
6
+ attribute :digest, String
7
+ attribute :avatar_digest, String
8
+ attribute :file_name, String
9
+ attribute :file_size, Fixnum
10
10
 
11
11
  def url(protocol='http')
12
12
  "#{protocol}://#{MLS.asset_host}/flyers/#{digest}/compressed/#{file_name}"
@@ -10,85 +10,85 @@ class MLS::Listing < MLS::Resource
10
10
  SOURCE_TYPES = %w(website flyer)
11
11
  CHANNELS = %w(excavator mls staircase broker_dashboard)
12
12
 
13
- property :id, Fixnum, :serialize => :false
14
- property :address_id, Fixnum, :serialize => :false
15
- property :slug, String, :serialize => :false
16
- property :use, String, :serialize => :if_present
17
- property :account_id, Fixnum
18
- property :private, Boolean, :default => false, :serialize => false
19
- property :source, String
20
- property :source_url, String
21
- property :source_type, String, :serialize => :if_present
22
- property :channel, String, :serialize => :if_present
23
- property :photo_ids, Array, :serialize => :if_present
24
-
25
- property :name, String
26
- property :type, String, :default => 'lease'
27
- property :workflow_state, String, :default => 'visible'
28
- property :lease_state, String, :default => 'listed'
29
- property :space_type, String, :default => 'unit'
30
- property :unit, String
31
- property :floor, Fixnum
32
- property :description, String
33
-
34
- property :size, Fixnum
35
- property :maximum_contiguous_size, Fixnum
36
- property :minimum_divisible_size, Fixnum
37
-
38
- property :amenities, Hash
39
- property :lease_terms, String
40
- property :rate, Decimal
41
- property :rate_units, String, :default => '/sqft/mo'
42
- property :low_rate, Decimal, :serialize => :false
43
- property :high_rate, Decimal, :serialize => :false
44
- property :sublease_expiration, DateTime
45
-
46
- property :forecast_rate_per_year, Decimal, :serialize => :false
47
- property :forecast_rate_per_month, Decimal, :serialize => :false
48
- property :forecast_rate_per_sqft_per_month, Decimal, :serialize => :false
49
- property :forecast_rate_per_sqft_per_year, Decimal, :serialize => :false
50
-
51
- property :available_on, DateTime
52
- property :term, Fixnum
53
- property :term_units, String, :default => 'years'
54
-
55
- property :weekday_hours, String
56
- property :saturday_hours, String
57
- property :sunday_hours, String
58
-
59
- property :offices, Fixnum
60
- property :desks, Fixnum
61
- property :conference_rooms, Fixnum
62
- property :bathrooms, Fixnum
63
-
64
- property :kitchen, Boolean
65
- property :showers, Boolean
66
- property :patio, Boolean
67
- property :reception_area, Boolean
68
- property :ready_to_move_in, Boolean
69
- property :furniture_available, Boolean
70
- property :natural_light, Boolean
71
- property :high_ceilings, Boolean
72
-
73
- property :created_at, DateTime, :serialize => :false
74
- property :updated_at, DateTime, :serialize => :false
75
- property :touched_at, DateTime, :serialize => :false
76
- property :leased_on, DateTime
77
- property :photography_requested_on, DateTime, :serialize => :false
78
-
79
- property :awesome_score, Fixnum
80
- property :awesome_needs, Array, :serialize => :if_present
81
- property :awesome_label, String
82
-
83
- property :flyer_id, Fixnum, :serialize => :if_present
84
- property :floorplan_id, Fixnum, :serialize => :if_present
85
-
86
- property :avatar_digest, String, :serialize => false
13
+ attribute :id, Fixnum, :serialize => :false
14
+ attribute :address_id, Fixnum, :serialize => :false
15
+ attribute :slug, String, :serialize => :false
16
+ attribute :use, String, :serialize => :if_present
17
+ attribute :account_id, Fixnum
18
+ attribute :private, Boolean, :default => false, :serialize => false
19
+ attribute :source, String
20
+ attribute :source_url, String
21
+ attribute :source_type, String, :serialize => :if_present
22
+ attribute :channel, String, :serialize => :if_present
23
+ attribute :photo_ids, Array, :serialize => :if_present
24
+
25
+ attribute :name, String
26
+ attribute :type, String, :default => 'lease'
27
+ attribute :workflow_state, String, :default => 'visible'
28
+ attribute :lease_state, String, :default => 'listed'
29
+ attribute :space_type, String, :default => 'unit'
30
+ attribute :unit, String
31
+ attribute :floor, Fixnum
32
+ attribute :description, String
33
+
34
+ attribute :size, Fixnum
35
+ attribute :maximum_contiguous_size, Fixnum
36
+ attribute :minimum_divisible_size, Fixnum
37
+
38
+ attribute :amenities, Hash
39
+ attribute :lease_terms, String
40
+ attribute :rate, Decimal
41
+ attribute :rate_units, String, :default => '/sqft/mo'
42
+ attribute :low_rate, Decimal, :serialize => :false
43
+ attribute :high_rate, Decimal, :serialize => :false
44
+ attribute :sublease_expiration, DateTime
45
+
46
+ attribute :forecast_rate_per_year, Decimal, :serialize => :false
47
+ attribute :forecast_rate_per_month, Decimal, :serialize => :false
48
+ attribute :forecast_rate_per_sqft_per_month, Decimal, :serialize => :false
49
+ attribute :forecast_rate_per_sqft_per_year, Decimal, :serialize => :false
50
+
51
+ attribute :available_on, DateTime
52
+ attribute :term, Fixnum
53
+ attribute :term_units, String, :default => 'years'
54
+
55
+ attribute :weekday_hours, String
56
+ attribute :saturday_hours, String
57
+ attribute :sunday_hours, String
58
+
59
+ attribute :offices, Fixnum
60
+ attribute :desks, Fixnum
61
+ attribute :conference_rooms, Fixnum
62
+ attribute :bathrooms, Fixnum
63
+
64
+ attribute :kitchen, Boolean
65
+ attribute :showers, Boolean
66
+ attribute :patio, Boolean
67
+ attribute :reception_area, Boolean
68
+ attribute :ready_to_move_in, Boolean
69
+ attribute :furniture_available, Boolean
70
+ attribute :natural_light, Boolean
71
+ attribute :high_ceilings, Boolean
72
+
73
+ attribute :created_at, DateTime, :serialize => :false
74
+ attribute :updated_at, DateTime, :serialize => :false
75
+ attribute :touched_at, DateTime, :serialize => :false
76
+ attribute :leased_on, DateTime
77
+ attribute :photography_requested_on, DateTime, :serialize => :false
78
+
79
+ attribute :awesome_score, Fixnum
80
+ attribute :awesome_needs, Array, :serialize => :if_present
81
+ attribute :awesome_label, String
82
+
83
+ attribute :flyer_id, Fixnum, :serialize => :if_present
84
+ attribute :floorplan_id, Fixnum, :serialize => :if_present
85
+
86
+ attribute :avatar_digest, String, :serialize => false
87
87
 
88
88
  # Counter Caches
89
- property :photos_count, Fixnum, :serialize => :false
89
+ attribute :photos_count, Fixnum, :serialize => :false
90
90
 
91
- attr_accessor :address, :agents, :account, :photos, :flyer, :floorplan, :videos, :similar_photos, :spaces, :primary_agent
91
+ attr_accessor :property, :address, :agents, :account, :photos, :flyer, :floorplan, :videos, :similar_photos, :spaces, :primary_agent
92
92
 
93
93
  def avatar(size='150x100#', protocol='http')
94
94
  if avatar_digest
@@ -380,6 +380,10 @@ class MLS::Listing::Parser < MLS::Parser
380
380
  @object.address = MLS::Address::Parser.build(address)
381
381
  end
382
382
 
383
+ def property=(property)
384
+ @object.property = MLS::Property::Parser.build(property)
385
+ end
386
+
383
387
  def agents=(agents)
384
388
  @object.agents = agents.map {|a| MLS::Account::Parser.build(a) }
385
389
  end