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/account.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
class Account < MLS::Model
|
2
|
+
|
3
|
+
include MLS::Avatar
|
4
|
+
|
5
|
+
belongs_to :brokerage
|
6
|
+
|
7
|
+
has_many :agencies, :inverse_of => :agent, :foreign_key => :agent_id
|
8
|
+
|
9
|
+
# def self.authenticate(email, pass)
|
10
|
+
# account = where(arel_table[:email].eq(email.try(:downcase)).and(arel_table[:password_digest].not_eq(nil))).first
|
11
|
+
# account && BCrypt::Password.new(account.password_digest) == pass ? account : nil
|
12
|
+
# end
|
13
|
+
|
14
|
+
|
15
|
+
end
|
data/lib/mls/address.rb
ADDED
data/lib/mls/agency.rb
ADDED
data/lib/mls/flyer.rb
ADDED
data/lib/mls/lease.rb
ADDED
data/lib/mls/listing.rb
ADDED
@@ -0,0 +1,135 @@
|
|
1
|
+
class Listing < MLS::Model
|
2
|
+
|
3
|
+
include MLS::Slugger
|
4
|
+
include MLS::Avatar
|
5
|
+
|
6
|
+
WORKFLOW_STATES = %w(visible processing invisible expired)
|
7
|
+
LEASE_STATES = %w(listed leased)
|
8
|
+
TYPES = %w(lease sublease coworking_space)
|
9
|
+
SPACE_TYPES = %w(unit floor building)
|
10
|
+
LEASE_TERMS = ['Full Service', 'NNN', 'Modified Gross']
|
11
|
+
RATE_UNITS = ['/sqft/yr', '/sqft/mo', '/mo', '/yr', '/desk/mo']
|
12
|
+
USES = ["Office", "Creative", "Loft", "Medical Office", "Flex Space", "R&D", "Office Showroom", "Industrial", "Retail"]
|
13
|
+
SOURCE_TYPES = %w(website flyer)
|
14
|
+
CHANNELS = %w(excavator mls staircase broker_dashboard)
|
15
|
+
|
16
|
+
belongs_to :property
|
17
|
+
belongs_to :floorplan
|
18
|
+
belongs_to :flyer
|
19
|
+
|
20
|
+
has_many :photos, -> { order('photos.order ASC') }, :as => :subject, :inverse_of => :subject
|
21
|
+
|
22
|
+
has_many :agencies, -> { order(:order) }, :as => :subject
|
23
|
+
has_many :agents, :through => :agencies, :source => :agent
|
24
|
+
|
25
|
+
# has_one :address
|
26
|
+
# has_one :contact
|
27
|
+
#
|
28
|
+
# has_many :addresses
|
29
|
+
|
30
|
+
# has_many :comments
|
31
|
+
# has_many :regions
|
32
|
+
# has_many :agents
|
33
|
+
|
34
|
+
# has_many :favoritizations, :foreign_key => :favorite_id
|
35
|
+
# has_many :accounts, :through => :favoritizations
|
36
|
+
# has_many :inquiries, :as => :subject, :inverse_of => :subject
|
37
|
+
# has_many :agencies, -> { order('"order"') }, :dependent => :destroy, :inverse_of => :subject, :as => :subject
|
38
|
+
# has_many :agents, -> { order('agencies.order') }, :through => :agencies, :inverse_of => :listings, :source => :agent
|
39
|
+
# has_many :email_proxies, :as => :subject, :inverse_of => :subject
|
40
|
+
# has_many :lead_listings, :dependent => :delete_all
|
41
|
+
#
|
42
|
+
has_and_belongs_to_many :uses
|
43
|
+
|
44
|
+
def contact
|
45
|
+
@contact ||= agents.first
|
46
|
+
end
|
47
|
+
alias_method :default_contact, :contact
|
48
|
+
|
49
|
+
def rate(units=nil)
|
50
|
+
return nil if !read_attribute(:rate)
|
51
|
+
units ||= rate_units
|
52
|
+
|
53
|
+
price = if rate_units == '/sqft/mo'
|
54
|
+
if units == '/sqft/mo'
|
55
|
+
read_attribute(:rate)
|
56
|
+
elsif units == '/sqft/yr'
|
57
|
+
read_attribute(:rate) * 12.0
|
58
|
+
elsif units == '/mo'
|
59
|
+
read_attribute(:rate) * size
|
60
|
+
elsif units == '/yr'
|
61
|
+
read_attribute(:rate) * size * 12.0
|
62
|
+
else
|
63
|
+
raise "Invalid rate conversion (#{rate_units} => #{units})"
|
64
|
+
end
|
65
|
+
|
66
|
+
elsif rate_units == '/sqft/yr'
|
67
|
+
if units == '/sqft/mo'
|
68
|
+
read_attribute(:rate) / 12.0
|
69
|
+
elsif units == '/sqft/yr'
|
70
|
+
read_attribute(:rate)
|
71
|
+
elsif units == '/mo'
|
72
|
+
(read_attribute(:rate) * size) / 12.0
|
73
|
+
elsif units == '/yr'
|
74
|
+
read_attribute(:rate) * size
|
75
|
+
else
|
76
|
+
raise "Invalid rate conversion (#{rate_units} => #{units})"
|
77
|
+
end
|
78
|
+
|
79
|
+
elsif rate_units == '/mo'
|
80
|
+
if units == '/sqft/mo'
|
81
|
+
read_attribute(:rate) / size.to_f
|
82
|
+
elsif units == '/sqft/yr'
|
83
|
+
(read_attribute(:rate) * 12) / size.to_f
|
84
|
+
elsif units == '/mo'
|
85
|
+
read_attribute(:rate)
|
86
|
+
elsif units == '/yr'
|
87
|
+
read_attribute(:rate) * 12
|
88
|
+
else
|
89
|
+
raise "Invalid rate conversion (#{rate_units} => #{units})"
|
90
|
+
end
|
91
|
+
|
92
|
+
elsif rate_units == '/yr'
|
93
|
+
if units == '/sqft/mo'
|
94
|
+
(read_attribute(:rate) / 12.0) / size.to_f
|
95
|
+
elsif units == '/sqft/yr'
|
96
|
+
read_attribute(:rate) / size.to_f
|
97
|
+
elsif units == '/mo'
|
98
|
+
read_attribute(:rate) / 12.0
|
99
|
+
elsif units == '/yr'
|
100
|
+
read_attribute(:rate)
|
101
|
+
else
|
102
|
+
raise "Invalid rate conversion (#{rate_units} => #{units})"
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
|
107
|
+
price.round(2)
|
108
|
+
end
|
109
|
+
|
110
|
+
def name
|
111
|
+
return read_attribute(:name) if read_attribute(:name)
|
112
|
+
|
113
|
+
case space_type
|
114
|
+
when 'unit'
|
115
|
+
if unit
|
116
|
+
"Unit #{unit}"
|
117
|
+
elsif floor
|
118
|
+
"#{floor.ordinalize} Floor Unit"
|
119
|
+
else
|
120
|
+
"Unit Lease"
|
121
|
+
end
|
122
|
+
when 'building'
|
123
|
+
"Entire Building"
|
124
|
+
when 'floor'
|
125
|
+
if floor
|
126
|
+
"#{floor.ordinalize} Floor"
|
127
|
+
elsif unit
|
128
|
+
"Unit #{unit}"
|
129
|
+
else
|
130
|
+
"Floor Lease"
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
end
|
data/lib/mls/locality.rb
ADDED
data/lib/mls/photo.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
class Photo < MLS::Model
|
2
|
+
|
3
|
+
belongs_to :subject, :polymorphic => true, :inverse_of => :photos
|
4
|
+
|
5
|
+
def url(options={})
|
6
|
+
options.reverse_merge!({
|
7
|
+
:style => nil,
|
8
|
+
:protocol => "http",
|
9
|
+
:bg => nil,
|
10
|
+
:format => "jpg"
|
11
|
+
});
|
12
|
+
url_params = {s: options[:style], bg: options[:bg]}.select{ |k, v| v }
|
13
|
+
result = "#{options[:protocol]}://#{MLS.image_host}/#{digest}.#{options[:format]}"
|
14
|
+
result += "?#{url_params.to_param}" if url_params.size > 0
|
15
|
+
|
16
|
+
result
|
17
|
+
end
|
18
|
+
end
|
data/lib/mls/property.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
class Property < MLS::Model
|
2
|
+
|
3
|
+
include MLS::Slugger
|
4
|
+
include MLS::Avatar
|
5
|
+
|
6
|
+
belongs_to :contact, :class_name => 'Account'
|
7
|
+
|
8
|
+
has_many :listings
|
9
|
+
has_many :localities
|
10
|
+
has_many :regions, :through => :localities
|
11
|
+
has_many :photos, -> { order('photos.order ASC') }, :as => :subject, :inverse_of => :subject
|
12
|
+
# has_many :regions
|
13
|
+
|
14
|
+
has_many :addresses
|
15
|
+
has_one :address, -> { where(:primary => true) }
|
16
|
+
|
17
|
+
def default_contact
|
18
|
+
@default_contact ||= listings.where(lease_state: :listed, state: :visible)
|
19
|
+
.where({ type: ['Lease', 'Sublease', 'Sale']})
|
20
|
+
.order(size: :desc)
|
21
|
+
.first.try(:contact)
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
data/lib/mls/region.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
class Region < MLS::Model
|
2
|
+
|
3
|
+
include MLS::Slugger
|
4
|
+
|
5
|
+
self.inheritance_column = 'inheritance_type'
|
6
|
+
|
7
|
+
belongs_to :cover_photo, :class_name => 'Photo'
|
8
|
+
|
9
|
+
has_and_belongs_to_many :parents, :join_table => 'regions_regions', :class_name => 'Region', :foreign_key => 'child_id', :association_foreign_key => 'parent_id'
|
10
|
+
has_and_belongs_to_many :children, :join_table => 'regions_regions', :class_name => 'Region', :foreign_key => 'parent_id', :association_foreign_key => 'child_id'
|
11
|
+
|
12
|
+
|
13
|
+
end
|
data/lib/mls/sale.rb
ADDED
data/lib/mls/space.rb
ADDED
data/lib/mls/sublease.rb
ADDED
data/lib/mls/use.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
class Use < MLS::Model
|
2
|
+
|
3
|
+
# has_ltree_hierarchy
|
4
|
+
|
5
|
+
has_many :children, class_name: 'Use', foreign_key: 'parent_id', inverse_of: :parent
|
6
|
+
|
7
|
+
has_and_belongs_to_many :listings
|
8
|
+
# has_and_belongs_to_many :properties
|
9
|
+
|
10
|
+
def descendants(uses = nil)
|
11
|
+
# Recursive self + children of children
|
12
|
+
uses ||= [self]
|
13
|
+
self.children.each do |child|
|
14
|
+
uses << child
|
15
|
+
uses = child.descendants(uses)
|
16
|
+
end
|
17
|
+
uses
|
18
|
+
end
|
19
|
+
|
20
|
+
# # Scope taken from https://github.com/RISCfuture/hierarchy/blob/master/lib/hierarchy.rb
|
21
|
+
# def self.self_and_descendents_of(use)
|
22
|
+
# where("path <@ ?", use.path)
|
23
|
+
# end
|
24
|
+
|
25
|
+
end
|
data/mls.gemspec
CHANGED
@@ -3,9 +3,9 @@ $:.push File.expand_path("../lib", __FILE__)
|
|
3
3
|
|
4
4
|
Gem::Specification.new do |s|
|
5
5
|
s.name = "mls"
|
6
|
-
s.version = '0.
|
7
|
-
s.authors = ["
|
8
|
-
s.email = ["james@42floors.com"]
|
6
|
+
s.version = '1.0.0'
|
7
|
+
s.authors = ["Jon Bracy", "James R. Bracy"]
|
8
|
+
s.email = ["jon@42floors.com", "james@42floors.com"]
|
9
9
|
s.homepage = "http://mls.42floors.com"
|
10
10
|
s.summary = %q{42Floors MLS Client}
|
11
11
|
s.description = %q{Ruby library for integrating with the 42Floors MLS}
|
@@ -22,18 +22,14 @@ Gem::Specification.new do |s|
|
|
22
22
|
s.add_development_dependency 'rdoc'
|
23
23
|
s.add_development_dependency 'sdoc'
|
24
24
|
s.add_development_dependency 'bundler'
|
25
|
-
s.add_development_dependency 'minitest'
|
26
|
-
s.add_development_dependency '
|
27
|
-
|
28
|
-
|
29
|
-
s.add_development_dependency '
|
25
|
+
s.add_development_dependency 'minitest'
|
26
|
+
s.add_development_dependency 'minitest-reporters'
|
27
|
+
s.add_development_dependency 'mocha'
|
28
|
+
s.add_development_dependency 'faker'
|
29
|
+
s.add_development_dependency 'factory_girl'
|
30
|
+
s.add_development_dependency 'webmock'
|
31
|
+
s.add_development_dependency 'sdoc-templates-42floors'
|
30
32
|
|
31
33
|
# Runtime
|
32
|
-
s.add_runtime_dependency '
|
33
|
-
# the gem provides factories, so this is required as a runtime dependency
|
34
|
-
s.add_runtime_dependency 'faker'
|
35
|
-
s.add_runtime_dependency 'factory_girl'
|
36
|
-
s.add_runtime_dependency 'yajl-ruby'
|
37
|
-
s.add_runtime_dependency 'rest-client'
|
38
|
-
|
34
|
+
s.add_runtime_dependency 'sunstone'
|
39
35
|
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class MLS::AttributeTest < Minitest::Test
|
4
|
+
|
5
|
+
test "::new(NAME) sets @name to NAME" do
|
6
|
+
attribute = MLS::Attribute.new("name")
|
7
|
+
assert_equal "name", attribute.name
|
8
|
+
end
|
9
|
+
|
10
|
+
test "::new(NAME) sets @options to defaults" do
|
11
|
+
attribute = MLS::Attribute.new("name")
|
12
|
+
assert_equal MLS::Attribute::DEFAULT_OPTIONS, attribute.options
|
13
|
+
end
|
14
|
+
|
15
|
+
test "::new(NAME) sets @instance_variable_name" do
|
16
|
+
attribute = MLS::Attribute.new("name")
|
17
|
+
assert_equal "@name", attribute.instance_variable_name
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
test "::new(NAME) sets @default to nil" do
|
22
|
+
attribute = MLS::Attribute.new("name")
|
23
|
+
assert_equal nil, attribute.default
|
24
|
+
end
|
25
|
+
|
26
|
+
test "::new(NAME, :default => N) sets @default to N" do
|
27
|
+
attribute = MLS::Attribute.new("name", :default => 'N')
|
28
|
+
assert_equal 'N', attribute.default
|
29
|
+
end
|
30
|
+
|
31
|
+
test "::new(NAME) sets @reader_visibility to :public" do
|
32
|
+
attribute = MLS::Attribute.new("name")
|
33
|
+
assert_equal :public, attribute.reader_visibility
|
34
|
+
end
|
35
|
+
|
36
|
+
test "::new(NAME, :reader => :private) sets @reader_visibility to :private" do
|
37
|
+
attribute = MLS::Attribute.new("name", :reader => :private)
|
38
|
+
assert_equal :private, attribute.reader_visibility
|
39
|
+
end
|
40
|
+
|
41
|
+
test "::new(NAME) sets @writer_visibility to :public" do
|
42
|
+
attribute = MLS::Attribute.new("name")
|
43
|
+
assert_equal :public, attribute.writer_visibility
|
44
|
+
end
|
45
|
+
|
46
|
+
test "::new(NAME, :writer => :private) sets @writer_visibility to :private" do
|
47
|
+
attribute = MLS::Attribute.new("name", :writer => :private)
|
48
|
+
assert_equal :private, attribute.writer_visibility
|
49
|
+
end
|
50
|
+
|
51
|
+
test "::demodulized_names caches hash" do
|
52
|
+
assert_equal MLS::Attribute.demodulized_names.object_id, MLS::Attribute.demodulized_names.object_id
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# require 'test_helper'
|
2
|
+
#
|
3
|
+
# class TestResource < MLS::Resource
|
4
|
+
# end
|
5
|
+
#
|
6
|
+
# class MLS::ResourceTest < Minitest::Test
|
7
|
+
#
|
8
|
+
# test "subclasses extend MLS::Model" do
|
9
|
+
# assert TestResource.kind_of?(MLS::Model)
|
10
|
+
# end
|
11
|
+
#
|
12
|
+
# test ""
|
13
|
+
#
|
14
|
+
# def test_instance_methods
|
15
|
+
# resource = TestResource.new
|
16
|
+
#
|
17
|
+
# assert resource.respond_to?(:new_record?)
|
18
|
+
# assert resource.respond_to?(:persisted?)
|
19
|
+
# assert resource.respond_to?(:save)
|
20
|
+
#
|
21
|
+
# assert resource.respond_to?(:attributes)
|
22
|
+
# assert resource.respond_to?(:set_default_values)
|
23
|
+
# assert resource.respond_to?(:update_attributes)
|
24
|
+
#
|
25
|
+
# assert resource.respond_to?(:to_hash)
|
26
|
+
# assert resource.respond_to?(:to_key)
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
# test 'save returns true || false'
|
30
|
+
#
|
31
|
+
# end
|