mls 0.14.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (80) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/Rakefile +6 -6
  4. data/lib/mls.rb +73 -427
  5. data/lib/mls/account.rb +15 -0
  6. data/lib/mls/address.rb +4 -0
  7. data/lib/mls/agency.rb +6 -0
  8. data/lib/mls/brokerage.rb +7 -0
  9. data/lib/mls/coworking_space.rb +5 -0
  10. data/lib/mls/floorplan.rb +11 -0
  11. data/lib/mls/flyer.rb +11 -0
  12. data/lib/mls/lease.rb +2 -0
  13. data/lib/mls/listing.rb +135 -0
  14. data/lib/mls/locality.rb +6 -0
  15. data/lib/mls/photo.rb +18 -0
  16. data/lib/mls/property.rb +24 -0
  17. data/lib/mls/region.rb +13 -0
  18. data/lib/mls/sale.rb +2 -0
  19. data/lib/mls/space.rb +3 -0
  20. data/lib/mls/sublease.rb +2 -0
  21. data/lib/mls/use.rb +25 -0
  22. data/mls.gemspec +11 -15
  23. data/test/mls/attribute_test.rb +55 -0
  24. data/test/mls/resource_test.rb +31 -0
  25. data/test/mls_test.rb +27 -0
  26. data/test/test_helper.rb +26 -27
  27. metadata +43 -75
  28. data/lib/mls/attribute.rb +0 -44
  29. data/lib/mls/attributes/array.rb +0 -11
  30. data/lib/mls/attributes/boolean.rb +0 -9
  31. data/lib/mls/attributes/datetime.rb +0 -25
  32. data/lib/mls/attributes/decimal.rb +0 -21
  33. data/lib/mls/attributes/fixnum.rb +0 -16
  34. data/lib/mls/attributes/hash.rb +0 -15
  35. data/lib/mls/attributes/string.rb +0 -15
  36. data/lib/mls/errors.rb +0 -29
  37. data/lib/mls/factories/account.rb +0 -34
  38. data/lib/mls/factories/address.rb +0 -16
  39. data/lib/mls/factories/listing.rb +0 -29
  40. data/lib/mls/factories_helper.rb +0 -7
  41. data/lib/mls/model.rb +0 -125
  42. data/lib/mls/models/account.rb +0 -174
  43. data/lib/mls/models/address.rb +0 -58
  44. data/lib/mls/models/brokerage.rb +0 -31
  45. data/lib/mls/models/floorplan.rb +0 -45
  46. data/lib/mls/models/flyer.rb +0 -45
  47. data/lib/mls/models/listing.rb +0 -394
  48. data/lib/mls/models/pdf.rb +0 -15
  49. data/lib/mls/models/photo.rb +0 -40
  50. data/lib/mls/models/property.rb +0 -114
  51. data/lib/mls/models/region.rb +0 -56
  52. data/lib/mls/models/tour.rb +0 -54
  53. data/lib/mls/models/video.rb +0 -18
  54. data/lib/mls/parser.rb +0 -74
  55. data/lib/mls/resource.rb +0 -99
  56. data/lib/rdoc/generator/template/42floors/_context.rhtml +0 -209
  57. data/lib/rdoc/generator/template/42floors/_head.rhtml +0 -7
  58. data/lib/rdoc/generator/template/42floors/class.rhtml +0 -39
  59. data/lib/rdoc/generator/template/42floors/file.rhtml +0 -35
  60. data/lib/rdoc/generator/template/42floors/index.rhtml +0 -13
  61. data/lib/rdoc/generator/template/42floors/resources/apple-touch-icon.png +0 -0
  62. data/lib/rdoc/generator/template/42floors/resources/css/github.css +0 -129
  63. data/lib/rdoc/generator/template/42floors/resources/css/main.css +0 -339
  64. data/lib/rdoc/generator/template/42floors/resources/css/panel.css +0 -389
  65. data/lib/rdoc/generator/template/42floors/resources/css/reset.css +0 -48
  66. data/lib/rdoc/generator/template/42floors/resources/favicon.ico +0 -0
  67. data/lib/rdoc/generator/template/42floors/resources/i/arrows.png +0 -0
  68. data/lib/rdoc/generator/template/42floors/resources/i/results_bg.png +0 -0
  69. data/lib/rdoc/generator/template/42floors/resources/i/tree_bg.png +0 -0
  70. data/lib/rdoc/generator/template/42floors/resources/js/highlight.pack.js +0 -1
  71. data/lib/rdoc/generator/template/42floors/resources/js/jquery-1.3.2.min.js +0 -19
  72. data/lib/rdoc/generator/template/42floors/resources/js/jquery-effect.js +0 -593
  73. data/lib/rdoc/generator/template/42floors/resources/js/main.js +0 -20
  74. data/lib/rdoc/generator/template/42floors/resources/js/searchdoc.js +0 -442
  75. data/lib/rdoc/generator/template/42floors/resources/panel/index.html +0 -73
  76. data/lib/rdoc/generator/template/42floors/se_index.rhtml +0 -8
  77. data/test/units/properties/test_boolean.rb +0 -4
  78. data/test/units/test_errors.rb +0 -32
  79. data/test/units/test_mls.rb +0 -294
  80. data/test/units/test_property.rb +0 -35
@@ -1,16 +0,0 @@
1
- class MLS::Attribute::Fixnum < ::MLS::Attribute
2
-
3
- def load(value) # from_json
4
- if value.nil?
5
- nil
6
- elsif value.is_a?(::Fixnum)
7
- value
8
- else
9
- value.to_i
10
- end
11
-
12
- end
13
-
14
- alias :dump :load #only for primatives
15
-
16
- end
@@ -1,15 +0,0 @@
1
- class MLS::Attribute::Hash < MLS::Attribute
2
-
3
- def load(value) # from_json
4
- if value.is_a?(Hash)
5
- value.with_indifferent_access
6
- else
7
- value
8
- end
9
- end
10
-
11
- def dump(value)
12
- value
13
- end
14
-
15
- end
@@ -1,15 +0,0 @@
1
- class MLS::Attribute::String < MLS::Attribute
2
-
3
- def load(value) # from_json
4
- if value.nil?
5
- nil
6
- elsif value.is_a?(::String)
7
- value
8
- else
9
- value.to_s
10
- end
11
- end
12
-
13
- alias :dump :load #only for primatives
14
-
15
- end
@@ -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
-
@@ -1,7 +0,0 @@
1
- require 'factory_girl'
2
-
3
- factories_dir = File.join(File.dirname(__FILE__), 'factories')
4
- FactoryGirl.definition_file_paths = [factories_dir]
5
- FactoryGirl.find_definitions
6
-
7
- MLS_GEM_CACHE={}
@@ -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
@@ -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