alt 1.0.1 → 2.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/CHANGELOG.md +24 -0
- data/README.md +54 -14
- data/lib/alt/property/climate.rb +58 -0
- data/lib/alt/property/described.rb +40 -0
- data/lib/alt/property/detailed.rb +19 -0
- data/lib/alt/property/exterior.rb +47 -0
- data/lib/alt/property/grounds.rb +44 -0
- data/lib/alt/property/placed.rb +16 -0
- data/lib/alt/property/structure.rb +34 -0
- data/lib/alt/property.rb +10 -4
- data/lib/alt/version.rb +1 -1
- data/lib/alt.rb +7 -0
- metadata +10 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ff6375beb17a5e6f0ff9244e5b87cc4906f717644a34228fa22e58e58137070d
|
|
4
|
+
data.tar.gz: 206eee4de38abd0d516a341d72830c973f6ddac5c0e0978370d21550e6c38acc
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 504da64a13fd24f9775f39533417c7875cb045f6c14e933a811a6e8dc8bbf5664a40b37901855bb7babc2766fdc8983f38b587de6c465a869fccd6f45d83b1ed
|
|
7
|
+
data.tar.gz: 07b2559f1ff20a650363c53980bb3588f581be639ab0e91f0d18903187df6c060c3c79e329fd78fc5f8430c15b17dcbb6f32984d1eae164c25e6bbdfa31df3bc
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,27 @@
|
|
|
1
|
+
## [Unreleased]
|
|
2
|
+
|
|
3
|
+
## [2.0.0] - 2026-09-10
|
|
4
|
+
|
|
5
|
+
- [Breaking change] `Alt::Property#property_details` is gone, and `#facts` answers in its
|
|
6
|
+
place. Where the old method handed back Realtor's whole 73-key document, the new one
|
|
7
|
+
answers only the facts worth keeping, each named by what it is: `Bedrooms`, `Lot size`
|
|
8
|
+
(in acres), `Living area`, `Bathrooms`, `Year built`, `Stories`, `Garage spaces`,
|
|
9
|
+
`Fireplaces`, `Property type`, `Heating system`, `Heating fuel`, `Cooling`, `Roof`,
|
|
10
|
+
`Construction`, `Sewer`, `Foundation`, `Pool`, `Outdoor living`, `Fence` and
|
|
11
|
+
`Sprinklers`. A fact the listing does not state is left out rather than answered as a
|
|
12
|
+
zero or a `false`, since the response cannot tell "no pool" from "no mention of a pool".
|
|
13
|
+
- [Feature] The MLS dialect a listing is written in is mapped onto a closed set of options.
|
|
14
|
+
One fact is spelled many ways — `Warm Air`, `Forced Air` and `ForcedAir` are one heating
|
|
15
|
+
system, `Asphalt Shingle`, `Composition` and `Architectural Shingles` are one roof — and
|
|
16
|
+
a comma-joined value carries two facts at once, so `Forced Air, Natural Gas` answers a
|
|
17
|
+
heating system and a heating fuel separately. Every option was derived from 329 real
|
|
18
|
+
enrichments, and everything the mapping does not name answers `Other`.
|
|
19
|
+
- [Feature] `Coordinate` answers the point Realtor places the home at, as `[lat, lon]`. It
|
|
20
|
+
is the one entry not meant for storage: a host pins the place with it and drops it, since
|
|
21
|
+
a precise coordinate kept beside a street is personal data.
|
|
22
|
+
- [Fix] An acre is 43,560 square feet, not 43,561. `Lot size` was previously computed by
|
|
23
|
+
whoever called this gem, using the second number.
|
|
24
|
+
|
|
1
25
|
## [1.0.1] - 2026-08-24
|
|
2
26
|
|
|
3
27
|
- [Fix] Raise Error when autocomplete doesn't return a valid address.
|
data/README.md
CHANGED
|
@@ -1,8 +1,27 @@
|
|
|
1
1
|
# Realtor API Ruby client
|
|
2
2
|
|
|
3
|
-
Fetches
|
|
3
|
+
Fetches the facts Realtor states about a home, reached through
|
|
4
4
|
[RapidAPI](https://rapidapi.com/apidojo/api/realty-in-us).
|
|
5
5
|
|
|
6
|
+
- Source: https://github.com/claudiob/alt
|
|
7
|
+
- API reference: https://rubydoc.info/gems/alt
|
|
8
|
+
|
|
9
|
+
## How to install
|
|
10
|
+
|
|
11
|
+
Install the gem system-wide:
|
|
12
|
+
|
|
13
|
+
```sh
|
|
14
|
+
gem install alt
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Or add it to a Gemfile, pinned to the current major:
|
|
18
|
+
|
|
19
|
+
```ruby
|
|
20
|
+
gem 'alt', '~> 2.0'
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
`~> major.minor` means `bundle update` never crosses a breaking change.
|
|
24
|
+
|
|
6
25
|
## Authentication
|
|
7
26
|
|
|
8
27
|
Subscribe to the Realtor API on RapidAPI and set your key as an environment variable:
|
|
@@ -16,11 +35,42 @@ The host (`realty-in-us.p.rapidapi.com`) is sent automatically as `X-RapidAPI-Ho
|
|
|
16
35
|
```ruby
|
|
17
36
|
property = Alt::Property.new address: "4352 Desert Park Ave", unit: nil, city: "North Las Vegas", zipcode: "89085"
|
|
18
37
|
|
|
19
|
-
property.
|
|
38
|
+
property.facts
|
|
39
|
+
# => { "Lot size" => 0.1837, "Living area" => 3000, "Bedrooms" => 5, "Bathrooms" => 2,
|
|
40
|
+
# "Year built" => 1999, "Stories" => 2, "Garage spaces" => 3, "Fireplaces" => 2,
|
|
41
|
+
# "Property type" => "Single family", "Heating system" => "Forced air",
|
|
42
|
+
# "Heating fuel" => "Natural gas", "Cooling" => "Central air",
|
|
43
|
+
# "Roof" => "Asphalt shingle", "Construction" => "Brick", "Sewer" => "Public",
|
|
44
|
+
# "Foundation" => "Slab", "Pool" => "Yes", "Outdoor living" => "Yes",
|
|
45
|
+
# "Fence" => "Yes", "Sprinklers" => "Yes", "Coordinate" => [36.2814, -115.1543] }
|
|
20
46
|
```
|
|
21
47
|
|
|
22
|
-
|
|
23
|
-
|
|
48
|
+
Every key is named after the fact it states, so a host stores each under whatever it calls
|
|
49
|
+
it. A fact the listing does not state is **left out** rather than answered as a zero or a
|
|
50
|
+
`false`: the response cannot tell "no pool" from "no mention of a pool", and a value that
|
|
51
|
+
says the second while meaning the first is worse than no value at all.
|
|
52
|
+
|
|
53
|
+
`Coordinate` is the one entry not meant for storage. It answers `[lat, lon]` so that a host
|
|
54
|
+
can place the home on a map; a precise coordinate kept beside a street address is personal
|
|
55
|
+
data, so pin with it and drop it.
|
|
56
|
+
|
|
57
|
+
Nothing else Realtor sends comes back. The response also carries the street, an `href`
|
|
58
|
+
whose slug is the street address, the listing agent's name, email and phones, and a Street
|
|
59
|
+
View URL embedding both the address and a live Maps key — an allow-list rather than a
|
|
60
|
+
deny-list is what keeps all of it out.
|
|
61
|
+
|
|
62
|
+
## How a fact is read
|
|
63
|
+
|
|
64
|
+
Realtor answers two blocks worth reading: `description`, which states the home's own
|
|
65
|
+
figures and its kind, and `details`, an array of `{ category, text[] }` where each `text`
|
|
66
|
+
entry is a `"Label: value"` sentence written in whichever dialect the listing MLS uses.
|
|
67
|
+
|
|
68
|
+
One fact is spelled many ways, and a comma-joined value carries two facts at once. So each
|
|
69
|
+
choice is mapped onto a closed set of options — `Warm Air`, `Forced Air` and `ForcedAir`
|
|
70
|
+
are all `Forced air`; `Forced Air, Natural Gas` answers a heating system *and* a heating
|
|
71
|
+
fuel — and anything the mapping does not name answers `Other`. The options were derived
|
|
72
|
+
from 329 real enrichments rather than from the API's documentation, which does not describe
|
|
73
|
+
these fields.
|
|
24
74
|
|
|
25
75
|
## How a lookup works
|
|
26
76
|
|
|
@@ -30,13 +80,3 @@ Realtor has no address-to-detail endpoint, so a lookup takes two requests:
|
|
|
30
80
|
2. `GET /properties/v3/detail?property_id=<id>` — returns the details
|
|
31
81
|
|
|
32
82
|
`Alt::Error` is raised when either request fails, or when the address matches no property.
|
|
33
|
-
|
|
34
|
-
## Status
|
|
35
|
-
|
|
36
|
-
The two endpoint paths above are confirmed to exist. The following identifiers are **not yet
|
|
37
|
-
verified against a live response** (the account's RapidAPI quota was exhausted at the time of
|
|
38
|
-
writing) and should be checked against the RapidAPI playground before relying on this client:
|
|
39
|
-
|
|
40
|
-
- the `input` query parameter name for `/locations/v2/auto-complete`
|
|
41
|
-
- the `autocomplete` array and its `mpr_id` field in that response
|
|
42
|
-
- the `property_id` query parameter name for `/properties/v3/detail`
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Alt
|
|
4
|
+
class Property
|
|
5
|
+
# Reads how a home is heated and cooled, which one line states in two parts.
|
|
6
|
+
module Climate
|
|
7
|
+
# The line an MLS states heating on, e.g. 'Heating Features: Forced Air, Natural Gas'.
|
|
8
|
+
HEATING = /\AHeating( Features| System)?\s*:/i
|
|
9
|
+
|
|
10
|
+
# The line it states cooling on, e.g. 'Cooling: Central Air'.
|
|
11
|
+
COOLING = /\ACooling( Features)?\s*:/i
|
|
12
|
+
|
|
13
|
+
private
|
|
14
|
+
|
|
15
|
+
def climate
|
|
16
|
+
heating = detail HEATING
|
|
17
|
+
{ 'Heating system' => heating_system_of(heating),
|
|
18
|
+
'Heating fuel' => heating_fuel_of(heating),
|
|
19
|
+
'Cooling' => cooling_of(detail(COOLING)), }.compact
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def heating_system_of(heating)
|
|
23
|
+
return unless heating
|
|
24
|
+
|
|
25
|
+
case heating
|
|
26
|
+
when /heat ?pump/i then 'Heat pump'
|
|
27
|
+
when /(warm|forced|hot) air|forcedair/i then 'Forced air'
|
|
28
|
+
when /hot water|forced water|radiator|steam|boiler/i then 'Hot water'
|
|
29
|
+
when /baseboard/i then 'Baseboard'
|
|
30
|
+
when /central/i then 'Central'
|
|
31
|
+
else 'Other'
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def heating_fuel_of(heating)
|
|
36
|
+
case heating
|
|
37
|
+
when /electric/i then 'Electric'
|
|
38
|
+
when /propane/i then 'Propane'
|
|
39
|
+
when /natural gas|\bgas\b/i then 'Natural gas'
|
|
40
|
+
when /\boil\b/i then 'Oil'
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def cooling_of(cooling)
|
|
45
|
+
return unless cooling
|
|
46
|
+
|
|
47
|
+
case cooling
|
|
48
|
+
when /central|package/i then 'Central air'
|
|
49
|
+
when /heat ?pump/i then 'Heat pump'
|
|
50
|
+
when /wall|window|room|individual/i then 'Wall or window'
|
|
51
|
+
when /evaporative/i then 'Evaporative'
|
|
52
|
+
when /fan/i then 'Ceiling fan'
|
|
53
|
+
else 'Other'
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Alt
|
|
4
|
+
class Property
|
|
5
|
+
# Reads Realtor's `description`, which states a home's own figures and its kind.
|
|
6
|
+
module Described
|
|
7
|
+
# The square feet in an acre, which is the unit a lot is worth storing in.
|
|
8
|
+
ACRE = 43_560.0
|
|
9
|
+
|
|
10
|
+
private
|
|
11
|
+
|
|
12
|
+
def described
|
|
13
|
+
{ 'Lot size' => acres, 'Living area' => description[:sqft],
|
|
14
|
+
'Bedrooms' => description[:beds], 'Bathrooms' => description[:baths],
|
|
15
|
+
'Year built' => description[:year_built], 'Stories' => description[:stories],
|
|
16
|
+
'Garage spaces' => description[:garage],
|
|
17
|
+
'Property type' => property_type_of(description[:type]), }.compact
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def acres
|
|
21
|
+
sqft = description[:lot_sqft]
|
|
22
|
+
sqft / ACRE if sqft
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def description = home[:description] || {}
|
|
26
|
+
|
|
27
|
+
def property_type_of(type)
|
|
28
|
+
return unless type
|
|
29
|
+
|
|
30
|
+
case type
|
|
31
|
+
when 'single_family' then 'Single family'
|
|
32
|
+
when /townhome/ then 'Townhome'
|
|
33
|
+
when 'condo', 'condos', 'apartment' then 'Condo'
|
|
34
|
+
when 'land', 'farm' then 'Land'
|
|
35
|
+
else 'Other'
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Alt
|
|
4
|
+
class Property
|
|
5
|
+
# Reads Realtor's `details`, whose lines are sentences labeled by what they state.
|
|
6
|
+
module Detailed
|
|
7
|
+
private
|
|
8
|
+
|
|
9
|
+
def detail(label)
|
|
10
|
+
line = detail_lines.grep(label).first
|
|
11
|
+
line.split(':', 2).last.strip if line
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def detail_lines
|
|
15
|
+
Array(home[:details]).flat_map { |one| Array one[:text] }
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Alt
|
|
4
|
+
class Property
|
|
5
|
+
# Reads what a home is roofed and clad with.
|
|
6
|
+
module Exterior
|
|
7
|
+
# The line an MLS states a roof on, e.g. 'Roof: Asphalt Shingle'.
|
|
8
|
+
ROOF = /\ARoof(ing)?\s*:/i
|
|
9
|
+
|
|
10
|
+
# The three headings it files the walls under, e.g. 'Construction Materials: Brick'.
|
|
11
|
+
CONSTRUCTION = /\A(Construction Materials|Building Exterior Type|Exterior)\s*:/i
|
|
12
|
+
|
|
13
|
+
private
|
|
14
|
+
|
|
15
|
+
def exterior
|
|
16
|
+
{ 'Roof' => roof_of(detail(ROOF)),
|
|
17
|
+
'Construction' => construction_of(detail(CONSTRUCTION)), }.compact
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def roof_of(roof)
|
|
21
|
+
return unless roof
|
|
22
|
+
|
|
23
|
+
case roof
|
|
24
|
+
when /tile/i then 'Tile'
|
|
25
|
+
when /slate|slag/i then 'Slate'
|
|
26
|
+
when /metal|corrugated/i then 'Metal'
|
|
27
|
+
when /wood|shake|cedar/i then 'Wood'
|
|
28
|
+
when /shingle|asphalt|composition|fiberglass/i then 'Asphalt shingle'
|
|
29
|
+
else 'Other'
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def construction_of(construction)
|
|
34
|
+
return unless construction
|
|
35
|
+
|
|
36
|
+
case construction
|
|
37
|
+
when /brick/i then 'Brick'
|
|
38
|
+
when /vinyl/i then 'Vinyl'
|
|
39
|
+
when /wood|cedar|clapboard|shake|frame/i then 'Wood'
|
|
40
|
+
when /aluminum/i then 'Aluminum'
|
|
41
|
+
when /stucco|plaster|stone|concrete|block|cement|hardi/i then 'Masonry'
|
|
42
|
+
else 'Other'
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Alt
|
|
4
|
+
class Property
|
|
5
|
+
# Reads what a home has outside its walls.
|
|
6
|
+
module Grounds
|
|
7
|
+
# A pool of the home's own, anchored so that a community one is not taken for one.
|
|
8
|
+
POOL = /\APool/i
|
|
9
|
+
|
|
10
|
+
# Somewhere to sit out, e.g. 'Patio And Porch Features: Covered, Deck'.
|
|
11
|
+
OUTDOOR = /\A(Patio|Deck|Porch)/i
|
|
12
|
+
|
|
13
|
+
# A fence, however the MLS spells it: 'Fencing', 'Fence YN', 'Fenced Yard'.
|
|
14
|
+
FENCE = /\AFenc/i
|
|
15
|
+
|
|
16
|
+
# An irrigation system, e.g. 'Sprinkler System'. A fire sprinkler is labeled otherwise.
|
|
17
|
+
SPRINKLERS = /\ASprinkler/i
|
|
18
|
+
|
|
19
|
+
# The four headings an MLS states where the waste goes under, e.g. 'Sewer: Public'.
|
|
20
|
+
SEWER = /\A(Sewer|Septic|City Sewer|Public Sewer)/i
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
|
|
24
|
+
def grounds
|
|
25
|
+
{ 'Pool' => ('Yes' if detail(POOL)),
|
|
26
|
+
'Outdoor living' => ('Yes' if detail(OUTDOOR)),
|
|
27
|
+
'Fence' => ('Yes' if detail(FENCE)),
|
|
28
|
+
'Sprinklers' => ('Yes' if detail(SPRINKLERS)),
|
|
29
|
+
'Sewer' => sewer_of(detail(SEWER)), }.compact
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def sewer_of(sewer)
|
|
33
|
+
return unless sewer
|
|
34
|
+
|
|
35
|
+
case sewer
|
|
36
|
+
when /septic/i then 'Septic'
|
|
37
|
+
when /private/i then 'Private'
|
|
38
|
+
when /public|city|municipal|connected/i then 'Public'
|
|
39
|
+
else 'Other'
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Alt
|
|
4
|
+
class Property
|
|
5
|
+
# Reads where Realtor says the home stands, which a host pins with rather than keeps.
|
|
6
|
+
module Placed
|
|
7
|
+
private
|
|
8
|
+
|
|
9
|
+
def placed
|
|
10
|
+
{ 'Coordinate' => coordinate.values_at(:lat, :lon) }
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def coordinate = home.dig(:location, :address, :coordinate) || {}
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Alt
|
|
4
|
+
class Property
|
|
5
|
+
# Reads what a home stands on and what is built into it.
|
|
6
|
+
module Structure
|
|
7
|
+
# The line an MLS states what the house stands on, e.g. 'Foundation Details: Slab'.
|
|
8
|
+
FOUNDATION = /\AFoundation/i
|
|
9
|
+
|
|
10
|
+
# A counted fireplace, since 'Fireplace features' describes them rather than counting.
|
|
11
|
+
FIREPLACES = /\A(Number of )?Fireplaces\b[^:]*:\s*\d/i
|
|
12
|
+
|
|
13
|
+
private
|
|
14
|
+
|
|
15
|
+
def structure
|
|
16
|
+
{ 'Foundation' => foundation_of(detail(FOUNDATION)),
|
|
17
|
+
'Fireplaces' => detail(FIREPLACES)&.to_i, }.compact
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def foundation_of(foundation)
|
|
21
|
+
return unless foundation
|
|
22
|
+
|
|
23
|
+
case foundation
|
|
24
|
+
when /slab/i then 'Slab'
|
|
25
|
+
when /crawl/i then 'Crawl space'
|
|
26
|
+
when /block/i then 'Block'
|
|
27
|
+
when /concrete|perimeter|poured/i then 'Concrete'
|
|
28
|
+
when /stone|brick/i then 'Stone'
|
|
29
|
+
else 'Other'
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
data/lib/alt/property.rb
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
# A wrapper for the Realtor API, reached through RapidAPI, to fetch property details.
|
|
2
4
|
# @see https://rapidapi.com/apidojo/api/realty-in-us
|
|
3
5
|
module Alt
|
|
4
6
|
# Embeds the logic of a Realtor property.
|
|
5
7
|
class Property
|
|
8
|
+
include Climate, Described, Detailed, Exterior, Grounds, Placed, Structure
|
|
9
|
+
|
|
6
10
|
# The RapidAPI host serving the Realtor data.
|
|
7
11
|
HOST = 'realty-in-us.p.rapidapi.com'
|
|
8
12
|
|
|
@@ -15,13 +19,15 @@ module Alt
|
|
|
15
19
|
@data = data
|
|
16
20
|
end
|
|
17
21
|
|
|
18
|
-
# @return [Hash]
|
|
19
|
-
def
|
|
22
|
+
# @return [Hash] every fact Realtor states about the property, named by what it is.
|
|
23
|
+
def facts = [climate, described, exterior, grounds, placed, structure].inject :merge
|
|
20
24
|
|
|
21
25
|
private
|
|
22
26
|
|
|
23
|
-
def
|
|
24
|
-
|
|
27
|
+
def home = response.dig(:data, :home) || {}
|
|
28
|
+
|
|
29
|
+
def response
|
|
30
|
+
@response ||= fetch
|
|
25
31
|
end
|
|
26
32
|
|
|
27
33
|
# Realtor exposes no address-to-detail endpoint, so the address is resolved to an id first.
|
data/lib/alt/version.rb
CHANGED
data/lib/alt.rb
CHANGED
|
@@ -6,4 +6,11 @@ require 'net/http'
|
|
|
6
6
|
require 'uri'
|
|
7
7
|
|
|
8
8
|
require 'alt/error'
|
|
9
|
+
require 'alt/property/climate'
|
|
10
|
+
require 'alt/property/described'
|
|
11
|
+
require 'alt/property/detailed'
|
|
12
|
+
require 'alt/property/exterior'
|
|
13
|
+
require 'alt/property/grounds'
|
|
14
|
+
require 'alt/property/placed'
|
|
15
|
+
require 'alt/property/structure'
|
|
9
16
|
require 'alt/property'
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: alt
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 2.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Claudio Baccigalupo
|
|
@@ -36,6 +36,13 @@ files:
|
|
|
36
36
|
- lib/alt.rb
|
|
37
37
|
- lib/alt/error.rb
|
|
38
38
|
- lib/alt/property.rb
|
|
39
|
+
- lib/alt/property/climate.rb
|
|
40
|
+
- lib/alt/property/described.rb
|
|
41
|
+
- lib/alt/property/detailed.rb
|
|
42
|
+
- lib/alt/property/exterior.rb
|
|
43
|
+
- lib/alt/property/grounds.rb
|
|
44
|
+
- lib/alt/property/placed.rb
|
|
45
|
+
- lib/alt/property/structure.rb
|
|
39
46
|
- lib/alt/version.rb
|
|
40
47
|
homepage: https://github.com/claudiob/alt
|
|
41
48
|
licenses:
|
|
@@ -43,7 +50,8 @@ licenses:
|
|
|
43
50
|
metadata:
|
|
44
51
|
homepage_uri: https://github.com/claudiob/alt
|
|
45
52
|
source_code_uri: https://github.com/claudiob/alt
|
|
46
|
-
changelog_uri: https://github.com/claudiob/alt
|
|
53
|
+
changelog_uri: https://github.com/claudiob/alt/blob/main/CHANGELOG.md
|
|
54
|
+
documentation_uri: https://rubydoc.info/gems/alt
|
|
47
55
|
rdoc_options: []
|
|
48
56
|
require_paths:
|
|
49
57
|
- lib
|