mits 0.0.1 → 0.1.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.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +9 -0
  3. data/{LICENSE.txt → LICENSE} +0 -0
  4. data/README.md +34 -16
  5. data/lib/mits/document.rb +35 -0
  6. data/lib/mits/entities/address.rb +16 -0
  7. data/lib/mits/entities/amenity.rb +8 -0
  8. data/lib/mits/entities/company.rb +11 -0
  9. data/lib/mits/entities/deposit.rb +11 -0
  10. data/lib/mits/entities/fees.rb +15 -0
  11. data/lib/mits/entities/file.rb +16 -0
  12. data/lib/mits/entities/pet.rb +11 -0
  13. data/lib/mits/entities/pet_policy.rb +15 -0
  14. data/lib/mits/entities/property.rb +20 -0
  15. data/lib/mits/entities/unit.rb +11 -0
  16. data/lib/mits/mapper.rb +48 -0
  17. data/lib/mits/mappers/address_mapper.rb +29 -0
  18. data/lib/mits/mappers/amenities_mapper.rb +14 -0
  19. data/lib/mits/mappers/company_mapper.rb +11 -0
  20. data/lib/mits/mappers/deposit_mapper.rb +24 -0
  21. data/lib/mits/mappers/fees_mapper.rb +15 -0
  22. data/lib/mits/mappers/files_mapper.rb +19 -0
  23. data/lib/mits/mappers/pet_policy_mapper.rb +28 -0
  24. data/lib/mits/mappers/property_mapper.rb +41 -0
  25. data/lib/mits/mappers/units_mapper.rb +22 -0
  26. data/lib/mits/saxerator_ext.rb +29 -0
  27. data/lib/mits/version.rb +2 -2
  28. data/lib/mits.rb +9 -3
  29. data/mits.gemspec +13 -6
  30. data/spec/fixtures/mits.xml +396 -0
  31. data/spec/fixtures/property.yml +205 -0
  32. data/spec/lib/mits/document_spec.rb +23 -0
  33. data/spec/lib/mits/entities/address_spec.rb +16 -0
  34. data/spec/lib/mits/entities/amenity_spec.rb +8 -0
  35. data/spec/lib/mits/entities/company_spec.rb +0 -0
  36. data/spec/lib/mits/entities/deposit_spec.rb +11 -0
  37. data/spec/lib/mits/entities/fees_spec.rb +15 -0
  38. data/spec/lib/mits/entities/file_spec.rb +17 -0
  39. data/spec/lib/mits/entities/pet_policy_spec.rb +14 -0
  40. data/spec/lib/mits/entities/pet_spec.rb +12 -0
  41. data/spec/lib/mits/entities/property_spec.rb +20 -0
  42. data/spec/lib/mits/entities/unit_spec.rb +11 -0
  43. data/spec/lib/mits/mapper_spec.rb +180 -0
  44. data/spec/spec_helper.rb +22 -0
  45. metadata +147 -8
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d505939145db141c682033bbf5d3fd1ef8062be3
4
- data.tar.gz: f130e83001a8be5634087fec84f6063ed6fa547d
3
+ metadata.gz: 9e3d066755e4fd3763ed195996832b597c6c559e
4
+ data.tar.gz: b9ad8637001201a6b12713c373971461c23cba9f
5
5
  SHA512:
6
- metadata.gz: baa3aa9da9b2b316eb3cd9ff74592c00e67499029bcffc153bd4193944aae24ddfd2df47bdeb8d1e337813ecebcdc032a5963229e518d22dbf8a07d15757b73c
7
- data.tar.gz: 004c18108965e715d0eeecaa1b6aee85d3e7ca25426c593ebf0cf008babca1e19a2ecffd7c705b4c1e880886f6594caa750540302ce83f414515e05eee7840ee
6
+ metadata.gz: 97d002c90c6ada433bf6a5bb5049ae129ecfa394c86036833f258aacc4bf3f5c3ed92f7c1d945d63801fddf04a7c5c04aec8079e88cfef17548f3fc6e1ce24b9
7
+ data.tar.gz: e917486f219ab2a63e3bdf52d5c77574bcbc6ee4021931295e5178281a8e34fe59d7037f35dbc1b0f7952fe683f81e8481b83d08c1c51f260958040a2c481bac
data/.travis.yml ADDED
@@ -0,0 +1,9 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1.1
4
+ - 2.0.0
5
+ - ruby-head
6
+ script: bundle exec rspec
7
+ matrix:
8
+ allow_failures:
9
+ - rvm: ruby-head
File without changes
data/README.md CHANGED
@@ -1,31 +1,49 @@
1
- # Mits
1
+ # MITS
2
2
 
3
- TODO: Write a gem description
3
+ A SAX powered reader for [Multifamily Information and Transactions Standard \(MITS\)](http://www.mitsproject.org/) compatible documents.
4
+
5
+ Currently supporting MITS __4.1__.
6
+
7
+ [![Gem Version](https://badge.fury.io/rb/mits.png)](https://rubygems.org/gems/mits) [![Build Status](https://travis-ci.org/doomspork/mits.svg?branch=master)](https://travis-ci.org/doomspork/mits) [![Code Climate](https://codeclimate.com/github/doomspork/mits/badges/gpa.svg)](https://codeclimate.com/github/doomspork/mits) [![Coverage Status](https://coveralls.io/repos/doomspork/mits/badge.png?branch=master)](https://coveralls.io/r/doomspork/mits?branch=master) [![Dependency Status](https://gemnasium.com/doomspork/mits.svg)](https://gemnasium.com/doomspork/mits)
4
8
 
5
9
  ## Installation
6
10
 
7
- Add this line to your application's Gemfile:
11
+ gem install mits
12
+
13
+ ## Getting Started
14
+
15
+ Create a `MITS::Document` with a local filepath or URL:
8
16
 
9
17
  ```ruby
10
- gem 'mits'
18
+ document = MITS::Document.new('/example/path/mits_compatible_feed.xml')
11
19
  ```
12
20
 
13
- And then execute:
21
+ Iterating over properties is easy:
14
22
 
15
- $ bundle
16
-
17
- Or install it yourself as:
23
+ ```ruby
24
+ document.properties do |property|
25
+ puts "#{property.name} now available online at #{property.website}"
26
+ end
27
+ ```
18
28
 
19
- $ gem install mits
29
+ The `#properties` method returns a `Enumerator` if no block is provided:
20
30
 
21
- ## Usage
31
+ ```ruby
22
32
 
23
- TODO: Write usage instructions here
33
+ document.properties.each_with_object([]) do |property, arr|
34
+ # Only include properties with 2 or more units
35
+ arr.push(property) if property.units.size > 2
36
+ end
37
+ ```
24
38
 
25
39
  ## Contributing
26
40
 
27
- 1. Fork it ( https://github.com/[my-github-username]/mits/fork )
28
- 2. Create your feature branch (`git checkout -b my-new-feature`)
29
- 3. Commit your changes (`git commit -am 'Add some feature'`)
30
- 4. Push to the branch (`git push origin my-new-feature`)
31
- 5. Create a new Pull Request
41
+ Feedback, feature requests, and fixes are welcome. Please make appropriate use of [Issues](https://github.com/doomspork/mits/issues) and [Pull Requests](https://github.com/doomspork/mits/pulls). All code should have accompanying tests.
42
+
43
+ ## Author
44
+
45
+ MITS is written and maintained by [@doomspork](http://github.com/doomspork) as part of [CityLeash](https://cityleash.com).
46
+
47
+ ## License
48
+
49
+ Please see [LICENSE](https://github.com/doomspork/mits/blob/master/LICENSE) for licensing details.
@@ -0,0 +1,35 @@
1
+ module MITS
2
+ class Document
3
+ attr_reader :parser
4
+
5
+ def initialize(url)
6
+ @parser = ::Saxerator.parser(open(url)) do |c|
7
+ c.put_attributes_in_hash!
8
+ c.symbolize_keys!
9
+ end
10
+ end
11
+
12
+ def properties
13
+ return enum_for(:properties) unless block_given?
14
+
15
+ physical_property.for_tag(:Property).each do |tag|
16
+ yield Mapper.property(tag)
17
+ end
18
+ end
19
+
20
+ def companies
21
+ return enum_for(:companies) unless block_given?
22
+
23
+ physical_property.within(:Management).within(:PropertyContacts).each do |tag|
24
+ yield Mapper.company(tag)
25
+ end
26
+ end
27
+
28
+ private
29
+
30
+ def physical_property
31
+ parser.within(:PhysicalProperty)
32
+ end
33
+
34
+ end
35
+ end
@@ -0,0 +1,16 @@
1
+ module MITS
2
+ class Address
3
+ include SimpleObjects::Base
4
+
5
+ attribute :address1
6
+ attribute :address2
7
+ attribute :city
8
+ attribute :country
9
+ attribute :description
10
+ attribute :latitude
11
+ attribute :longitude
12
+ attribute :postal_code
13
+ attribute :state
14
+ attribute :type
15
+ end
16
+ end
@@ -0,0 +1,8 @@
1
+ module MITS
2
+ class Amenity
3
+ include SimpleObjects::Base
4
+
5
+ attribute :description
6
+ attribute :type
7
+ end
8
+ end
@@ -0,0 +1,11 @@
1
+ module MITS
2
+ class Company
3
+ include SimpleObjects::Base
4
+
5
+ attribute :id
6
+ attribute :name
7
+ attribute :address
8
+ attribute :website
9
+ attribute :logo
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module MITS
2
+ class Deposit
3
+ include SimpleObjects::Base
4
+
5
+ attribute :amount
6
+ attribute :description
7
+ attribute :percent_refundable
8
+ attribute :portion_refundable
9
+ attribute :type
10
+ end
11
+ end
@@ -0,0 +1,15 @@
1
+ module MITS
2
+ class Fees
3
+ include SimpleObjects::Base
4
+
5
+ attribute :admin_fee
6
+ attribute :application_fee
7
+ attribute :broker_fee
8
+ attribute :late_fee_per_day
9
+ attribute :late_min_fee
10
+ attribute :late_percent
11
+ attribute :late_type
12
+ attribute :non_refundable_hold_fee
13
+ attribute :prorate_type
14
+ end
15
+ end
@@ -0,0 +1,16 @@
1
+ module MITS
2
+ class File
3
+ include SimpleObjects::Base
4
+
5
+ attribute :active
6
+ attribute :caption
7
+ attribute :description
8
+ attribute :format
9
+ attribute :height
10
+ attribute :id
11
+ attribute :name
12
+ attribute :rank
13
+ attribute :source
14
+ attribute :width
15
+ end
16
+ end
@@ -0,0 +1,11 @@
1
+ module MITS
2
+ class Pet
3
+ include SimpleObjects::Base
4
+
5
+ attribute :count
6
+ attribute :description
7
+ attribute :size
8
+ attribute :type
9
+ attribute :weight
10
+ end
11
+ end
@@ -0,0 +1,15 @@
1
+ module MITS
2
+ class PetPolicy
3
+ include SimpleObjects::Base
4
+
5
+ attribute :allowed
6
+ attribute :care
7
+ attribute :deposit
8
+ attribute :fee
9
+ attribute :pets
10
+ attribute :rent
11
+ attribute :restrictions
12
+
13
+ alias_method :allowed?, :allowed
14
+ end
15
+ end
@@ -0,0 +1,20 @@
1
+ module MITS
2
+ class Property
3
+ include SimpleObjects::Base
4
+
5
+ attribute :address
6
+ attribute :amenities
7
+ attribute :company_id
8
+ attribute :deposit
9
+ attribute :description
10
+ attribute :fees
11
+ attribute :files
12
+ attribute :id
13
+ attribute :name
14
+ attribute :pet_policy
15
+ attribute :summary
16
+ attribute :type
17
+ attribute :units
18
+ attribute :website
19
+ end
20
+ end
@@ -0,0 +1,11 @@
1
+ module MITS
2
+ class Unit
3
+ include SimpleObjects::Base
4
+
5
+ attribute :bathrooms
6
+ attribute :bedrooms
7
+ attribute :name
8
+ attribute :rent
9
+ attribute :sqft
10
+ end
11
+ end
@@ -0,0 +1,48 @@
1
+ require 'mits/entities/address'
2
+ require 'mits/entities/amenity'
3
+ require 'mits/entities/company'
4
+ require 'mits/entities/deposit'
5
+ require 'mits/entities/fees'
6
+ require 'mits/entities/file'
7
+ require 'mits/entities/pet'
8
+ require 'mits/entities/pet_policy'
9
+ require 'mits/entities/property'
10
+ require 'mits/entities/unit'
11
+
12
+ require 'mits/mappers/address_mapper'
13
+ require 'mits/mappers/amenities_mapper'
14
+ require 'mits/mappers/company_mapper'
15
+ require 'mits/mappers/deposit_mapper'
16
+ require 'mits/mappers/fees_mapper'
17
+ require 'mits/mappers/files_mapper'
18
+ require 'mits/mappers/pet_policy_mapper'
19
+ require 'mits/mappers/property_mapper'
20
+ require 'mits/mappers/units_mapper'
21
+
22
+ module MITS
23
+ module Mapper
24
+ extend AddressMapper
25
+ extend AmenitiesMapper
26
+ extend CompanyMapper
27
+ extend DepositMapper
28
+ extend FeesMapper
29
+ extend FilesMapper
30
+ extend PetPolicyMapper
31
+ extend PropertyMapper
32
+ extend UnitsMapper
33
+
34
+ extend self
35
+
36
+ protected
37
+
38
+ def bool(value)
39
+ value == 'true'
40
+ end
41
+
42
+ def try(value, method)
43
+ return nil unless value
44
+ value.send(method)
45
+ end
46
+
47
+ end
48
+ end
@@ -0,0 +1,29 @@
1
+ module MITS
2
+ module AddressMapper
3
+ def address(tag, secondary_tag = nil)
4
+ attrs = address_attributes(tag)
5
+
6
+ if secondary_tag
7
+ attrs[:latitude] = try(secondary_tag[:Latitude], :to_f)
8
+ attrs[:longitude] = try(secondary_tag[:Longitude], :to_f)
9
+ end
10
+
11
+ Address.new(attrs)
12
+ end
13
+
14
+ private
15
+
16
+ def address_attributes(tag)
17
+ {
18
+ type: tag[:AddressType],
19
+ description: tag[:Description],
20
+ address1: tag[:AddressLine1],
21
+ address2: tag[:AddressLine2],
22
+ city: tag[:City],
23
+ state: tag[:State],
24
+ postal_code: tag[:PostalCode],
25
+ country: tag[:Country],
26
+ }
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,14 @@
1
+ module MITS
2
+ module AmenitiesMapper
3
+ def amenities(tags)
4
+ if tags
5
+ tags = [tags] unless tags.is_a? Array
6
+ tags.map { |tag| amenity(tag) }
7
+ end
8
+ end
9
+
10
+ def amenity(tag)
11
+ Amenity.new(description: tag[:Description], type: tag[:AmenityType])
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,11 @@
1
+ module MITS
2
+ module CompanyMapper
3
+ def company(tag)
4
+ Company.new(address: address(tag[:Address]),
5
+ id: tag[:Identification][:IDValue],
6
+ logo: tag[:Logo],
7
+ name: tag[:CompanyName],
8
+ website: tag[:Website])
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,24 @@
1
+ module MITS
2
+ module DepositMapper
3
+ def deposit(tag)
4
+ Deposit.new(amount: deposit_amount(tag[:Amount][:ValueRange]),
5
+ description: tag[:Description],
6
+ percent_refundable: try(tag[:PercentRefundable], :to_f),
7
+ portion_refundable: try(tag[:PortionRefundable], :to_f),
8
+ type: tag[:DepositType])
9
+ end
10
+
11
+ private
12
+
13
+ def deposit_amount(tag)
14
+ if tag[:Exact]
15
+ amount = tag[:Exact].to_f
16
+ else
17
+ min = tag[:Min].to_f
18
+ max = tag[:Max].to_f
19
+ amount = Range.new(min, max)
20
+ end
21
+ amount
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,15 @@
1
+ module MITS
2
+ module FeesMapper
3
+ def fees(tag)
4
+ Fees.new(admin_fee: try(tag[:AdminFee], :to_f),
5
+ application_fee: try(tag[:ApplicationFee], :to_f),
6
+ broker_fee: try(tag[:BrokerFee], :to_f),
7
+ late_fee_per_day: try(tag[:LateFeePerDay], :to_f),
8
+ late_min_fee: try(tag[:LateMinFee], :to_f),
9
+ late_percent: try(tag[:LatePercent], :to_f),
10
+ late_type: tag[:LateType],
11
+ non_refundable_hold_fee: try(tag[:NonRefundableHoldFee], :to_f),
12
+ prorate_type: tag[:ProrateType])
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,19 @@
1
+ module MITS
2
+ module FilesMapper
3
+ def files(tags)
4
+ tags = [tags] unless tags.is_a? Array
5
+ tags.map do |tag|
6
+ File.new(active: bool(tag[:Active]),
7
+ caption: tag[:Caption],
8
+ description: tag[:Description],
9
+ format: tag[:Format],
10
+ height: try(tag[:Height], :to_i),
11
+ id: tag[:FileID],
12
+ name: tag[:Name],
13
+ rank: tag[:Rank],
14
+ source: tag[:Src],
15
+ width: tag[:Width])
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,28 @@
1
+ module MITS
2
+ module PetPolicyMapper
3
+ def pet_policy(tag)
4
+ if bool(tag[:Allowed])
5
+ PetPolicy.new(allowed: true,
6
+ care: bool(tag[:PetCare]),
7
+ deposit: try(tag[:Deposit], :to_f),
8
+ fee: try(tag[:Fee], :to_f),
9
+ pets: pets(tag[:Pets]),
10
+ rent: try(tag[:Rent], :to_f),
11
+ restrictions: tag[:Restrictions])
12
+ else
13
+ PetPolicy.new(allowed: false)
14
+ end
15
+ end
16
+
17
+ def pets(tags)
18
+ tags = [tags] unless tags.is_a? Array
19
+ tags.map do |tag|
20
+ Pet.new(count: tag[:Count].to_i,
21
+ description: tag[:Description],
22
+ size: tag[:Size],
23
+ weight: tag[:Weight],
24
+ type: tag[:PetType])
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,41 @@
1
+ module MITS
2
+ module PropertyMapper
3
+ def property(tag)
4
+ basics = property_basics(tag)
5
+ details = property_details(tag)
6
+ Property.new(basics.merge(details))
7
+ end
8
+
9
+ private
10
+
11
+ def property_basics(tag)
12
+ propId = tag[:PropertyID]
13
+ {
14
+ company_id: company_id(propId[:Identification]),
15
+ description: tag[:Information][:LongDescription],
16
+ id: tag[:IDValue],
17
+ name: propId[:MarketingName],
18
+ summary: tag[:Information][:ShortDescription],
19
+ type: tag[:ILS_Identification][:ILS_IdentificationType],
20
+ website: propId[:WebSite]
21
+ }
22
+ end
23
+
24
+ def property_details(tag)
25
+ {
26
+ address: address(tag[:PropertyID][:Address], tag[:ILS_Identification]),
27
+ amenities: amenities(tag[:ILS_Unit][:Amenity]),
28
+ deposit: deposit(tag[:Deposit]),
29
+ fees: fees(tag[:Fee]),
30
+ files: files(tag[:File]),
31
+ pet_policy: pet_policy(tag[:Policy][:Pet]),
32
+ units: units(tag[:ILS_Unit][:Units][:Unit])
33
+ }
34
+ end
35
+
36
+ def company_id(tags)
37
+ tag = tags.find { |t| t[:IDType].downcase == 'company' }
38
+ tag[:IDValue] if tag
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,22 @@
1
+ module MITS
2
+ module UnitsMapper
3
+ def units(tags)
4
+ tags = [tags] unless tags.is_a? Array
5
+ tags.map do |tag|
6
+ Unit.new(bathrooms: try(tag[:UnitBathrooms], :to_f),
7
+ bedrooms: try(tag[:UnitBedrooms], :to_f),
8
+ name: tag[:MarketingName],
9
+ rent: try(tag[:UnitRent], :to_f),
10
+ sqft: unit_sqft(tag))
11
+ end
12
+ end
13
+
14
+ private
15
+
16
+ def unit_sqft(tag)
17
+ min = tag[:MinSquareFeet]
18
+ max = tag[:MaxSquareFeet]
19
+ Range.new(min.to_i, max.to_i)
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,29 @@
1
+ module Saxerator
2
+ module Builder
3
+ class HashElement < Hash
4
+ def deep_hash
5
+ self.reduce({}) do |memo, (key, value)|
6
+ as_hash = if value.is_a? Array
7
+ value.map { |v| try_hash(v) }
8
+ else
9
+ try_hash(value)
10
+ end
11
+ memo[key] = as_hash
12
+ memo
13
+ end
14
+ end
15
+
16
+ def try_hash(val)
17
+ if val.is_a? EmptyElement
18
+ nil
19
+ elsif val.respond_to? :deep_hash
20
+ val.deep_hash
21
+ elsif val.respond_to? :to_h
22
+ val.to_h
23
+ else
24
+ val
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
data/lib/mits/version.rb CHANGED
@@ -1,3 +1,3 @@
1
- module Mits
2
- VERSION = "0.0.1"
1
+ module MITS
2
+ VERSION = '0.1.0'
3
3
  end
data/lib/mits.rb CHANGED
@@ -1,5 +1,11 @@
1
- require "mits/version"
1
+ require 'open-uri'
2
+ require 'saxerator'
3
+ require 'simple_objects'
2
4
 
3
- module Mits
4
- # Your code goes here...
5
+ require 'mits/document'
6
+ require 'mits/mapper'
7
+ require 'mits/saxerator_ext'
8
+ require 'mits/version'
9
+
10
+ module MITS
5
11
  end
data/mits.gemspec CHANGED
@@ -5,11 +5,11 @@ require 'mits/version'
5
5
 
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = 'mits'
8
- spec.version = Mits::VERSION
8
+ spec.version = MITS::VERSION
9
9
  spec.authors = ['Sean Callan']
10
10
  spec.email = ['seancallan@gmail.com']
11
- spec.summary = 'A SAX powered MITS reader.'
12
- spec.description = ''
11
+ spec.summary = 'A SAX powered MITS reader for Ruby.'
12
+ spec.description = 'A SAX powered Multifamily Information and Transactions Standard (MITS) reader for Ruby.'
13
13
  spec.homepage = 'https://github.com/doomspork/mits'
14
14
  spec.license = 'MIT'
15
15
 
@@ -18,7 +18,14 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ['lib']
20
20
 
21
- spec.add_dependency 'simple_objects', '~> 0.1'
22
- spec.add_development_dependency 'bundler', '~> 1.7'
23
- spec.add_development_dependency 'rake', '~> 10.0'
21
+ spec.add_dependency 'simple_objects', '~> 1.1'
22
+ spec.add_dependency 'saxerator', '~> 0.9.5'
23
+
24
+ spec.add_development_dependency 'bundler', '~> 1.7'
25
+ spec.add_development_dependency 'coveralls', '~> 0.7'
26
+ spec.add_development_dependency 'pry', '~> 0.10'
27
+ spec.add_development_dependency 'pry-byebug', '~> 2.0'
28
+ spec.add_development_dependency 'rake', '~> 10.0'
29
+ spec.add_development_dependency 'rspec', '~> 3.1'
30
+ spec.add_development_dependency 'simplecov', '~> 0.9'
24
31
  end