extraspace 0.1.2 → 0.3.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/README.md +10 -13
- data/exe/extraspace +7 -0
- data/lib/extraspace/address.rb +15 -16
- data/lib/extraspace/cli.rb +58 -0
- data/lib/extraspace/crawler.rb +2 -2
- data/lib/extraspace/dimensions.rb +9 -11
- data/lib/extraspace/facility.rb +60 -23
- data/lib/extraspace/geocode.rb +6 -1
- data/lib/extraspace/price.rb +13 -17
- data/lib/extraspace/rates.rb +7 -10
- data/lib/extraspace/sitemap.rb +2 -0
- data/lib/extraspace/version.rb +1 -1
- data/lib/extraspace.rb +1 -0
- metadata +20 -4
- data/lib/extraspace/availability.rb +0 -30
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e31518705b665cfcff3914a8553164f1463a3c66140cb41ea14be9154abf44fa
|
4
|
+
data.tar.gz: bf86b8674cf0557e239b286acaca2f77d1688bd3f431434ad15914db9624a143
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6204e8de2f7349debac7049c5ca1ade4fc0b5328be5faaf61eefb42d982e735897c28fc6292ac98c6a40e36dadf94550fcd30f5a066b3eb58ba8de7db3c2c20d
|
7
|
+
data.tar.gz: edd94f3a7d6dadc415f112f7dd3fa1ff7e8ae5fd8592794e3a218a3806e5ec7777659eeaee3bde305af51eee67f23fb5b5862925f51fc54d22ff5aa5ad863f34
|
data/README.md
CHANGED
@@ -20,23 +20,20 @@ require 'extraspace'
|
|
20
20
|
sitemap = ExtraSpace::Facility.sitemap
|
21
21
|
sitemap.links.each do |link|
|
22
22
|
url = link.loc
|
23
|
-
|
24
23
|
facility = ExtraSpace::Facility.fetch(url:)
|
25
24
|
|
26
|
-
puts
|
27
|
-
puts "Line 2: #{facility.address.line2}"
|
28
|
-
puts "City: #{facility.address.city}"
|
29
|
-
puts "State: #{facility.address.state}"
|
30
|
-
puts "ZIP: #{facility.address.zip}"
|
31
|
-
puts "Latitude: #{facility.geocode.latitude}"
|
32
|
-
puts "Longitude: #{facility.geocode.longitude}"
|
33
|
-
puts
|
25
|
+
puts facility.text
|
34
26
|
|
35
27
|
facility.prices.each do |price|
|
36
|
-
puts
|
37
|
-
puts "Dimensions: #{price.dimensions.display}"
|
38
|
-
puts "Rates: $#{price.rates.street} (street) / $#{price.rates.web} (web)"
|
39
|
-
puts
|
28
|
+
puts price.text
|
40
29
|
end
|
30
|
+
|
31
|
+
puts
|
41
32
|
end
|
42
33
|
```
|
34
|
+
|
35
|
+
## CLI
|
36
|
+
|
37
|
+
```bash
|
38
|
+
extraspace crawl
|
39
|
+
```
|
data/exe/extraspace
ADDED
data/lib/extraspace/address.rb
CHANGED
@@ -1,15 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ExtraSpace
|
4
|
-
#
|
4
|
+
# The address (street + city + state + zip) of a facility.
|
5
5
|
class Address
|
6
|
-
# @attribute [rw]
|
6
|
+
# @attribute [rw] street
|
7
7
|
# @return [String]
|
8
|
-
attr_accessor :
|
9
|
-
|
10
|
-
# @attribute [rw] line2
|
11
|
-
# @return [String]
|
12
|
-
attr_accessor :line2
|
8
|
+
attr_accessor :street
|
13
9
|
|
14
10
|
# @attribute [rw] city
|
15
11
|
# @return [String]
|
@@ -23,14 +19,12 @@ module ExtraSpace
|
|
23
19
|
# @return [String]
|
24
20
|
attr_accessor :zip
|
25
21
|
|
26
|
-
# @param
|
27
|
-
# @param line2 [String]
|
22
|
+
# @param street [String]
|
28
23
|
# @param city [String]
|
29
24
|
# @param state [String]
|
30
25
|
# @param zip [String]
|
31
|
-
def initialize(
|
32
|
-
@
|
33
|
-
@line2 = line2
|
26
|
+
def initialize(street:, city:, state:, zip:)
|
27
|
+
@street = street
|
34
28
|
@city = city
|
35
29
|
@state = state
|
36
30
|
@zip = zip
|
@@ -39,8 +33,7 @@ module ExtraSpace
|
|
39
33
|
# @return [String]
|
40
34
|
def inspect
|
41
35
|
props = [
|
42
|
-
"
|
43
|
-
"line2=#{@line2.inspect}",
|
36
|
+
"street=#{@street.inspect}",
|
44
37
|
"city=#{@city.inspect}",
|
45
38
|
"state=#{@state.inspect}",
|
46
39
|
"zip=#{@zip.inspect}"
|
@@ -48,13 +41,19 @@ module ExtraSpace
|
|
48
41
|
"#<#{self.class.name} #{props.join(' ')}>"
|
49
42
|
end
|
50
43
|
|
44
|
+
# @return [String]
|
45
|
+
def text
|
46
|
+
"#{street}, #{city}, #{state} #{zip}"
|
47
|
+
end
|
48
|
+
|
51
49
|
# @param data [Hash]
|
52
50
|
#
|
53
51
|
# @return [Address]
|
54
52
|
def self.parse(data:)
|
53
|
+
lines = %w[line1 line2 line3 line4].map { |key| data[key] }
|
54
|
+
|
55
55
|
new(
|
56
|
-
|
57
|
-
line2: data['line2'],
|
56
|
+
street: lines.compact.reject(&:empty?).join(' '),
|
58
57
|
city: data['city'],
|
59
58
|
state: data['stateName'],
|
60
59
|
zip: data['postalCode']
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'optparse'
|
4
|
+
|
5
|
+
module ExtraSpace
|
6
|
+
# Used when interacting with the library from the command line interface (CLI).
|
7
|
+
#
|
8
|
+
# Usage:
|
9
|
+
#
|
10
|
+
# cli = ExtraSpace::CLI.new
|
11
|
+
# cli.parse
|
12
|
+
class CLI
|
13
|
+
module Code
|
14
|
+
OK = 0
|
15
|
+
ERROR = 1
|
16
|
+
end
|
17
|
+
|
18
|
+
# @param argv [Array<String>]
|
19
|
+
def parse(argv = ARGV)
|
20
|
+
parser.parse!(argv)
|
21
|
+
command = argv.shift
|
22
|
+
|
23
|
+
case command
|
24
|
+
when 'crawl' then crawl
|
25
|
+
else
|
26
|
+
warn("unsupported command=#{command.inspect}")
|
27
|
+
exit(Code::ERROR)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def crawl
|
34
|
+
ExtraSpace::Facility.crawl
|
35
|
+
exit(Code::OK)
|
36
|
+
end
|
37
|
+
|
38
|
+
def help(options)
|
39
|
+
puts(options)
|
40
|
+
exit(Code::OK)
|
41
|
+
end
|
42
|
+
|
43
|
+
def version
|
44
|
+
puts(VERSION)
|
45
|
+
exit(Code::OK)
|
46
|
+
end
|
47
|
+
|
48
|
+
# @return [OptionParser]
|
49
|
+
def parser
|
50
|
+
OptionParser.new do |options|
|
51
|
+
options.banner = 'usage: extraspace [options] <command> [<args>]'
|
52
|
+
|
53
|
+
options.on('-h', '--help', 'help') { help(options) }
|
54
|
+
options.on('-v', '--version', 'version') { version }
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
data/lib/extraspace/crawler.rb
CHANGED
@@ -8,7 +8,7 @@ module ExtraSpace
|
|
8
8
|
# @param url [String]
|
9
9
|
# @param response [HTTP::Response]
|
10
10
|
def initialize(url:, response:)
|
11
|
-
super("url=#{url} status=#{response.status.inspect} body=#{response.body.inspect}")
|
11
|
+
super("url=#{url} status=#{response.status.inspect} body=#{String(response.body).inspect}")
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
@@ -30,7 +30,7 @@ module ExtraSpace
|
|
30
30
|
# @return [HTTP::Response]
|
31
31
|
def fetch(url:)
|
32
32
|
response = HTTP.get(url)
|
33
|
-
raise FetchError(url:, response: response.flush) unless response.status.ok?
|
33
|
+
raise FetchError.new(url:, response: response.flush) unless response.status.ok?
|
34
34
|
|
35
35
|
response
|
36
36
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ExtraSpace
|
4
|
-
#
|
4
|
+
# The dimensions (width + depth + sqft) of a price.
|
5
5
|
class Dimensions
|
6
6
|
# @attribute [rw] depth
|
7
7
|
# @return [Integer]
|
@@ -15,19 +15,13 @@ module ExtraSpace
|
|
15
15
|
# @return [Integer]
|
16
16
|
attr_accessor :sqft
|
17
17
|
|
18
|
-
# @attribute [rw] display
|
19
|
-
# @return [String]
|
20
|
-
attr_accessor :display
|
21
|
-
|
22
18
|
# @param depth [Integer]
|
23
19
|
# @param width [Integer]
|
24
20
|
# @param sqft [Integer]
|
25
|
-
|
26
|
-
def initialize(depth:, width:, sqft:, display:)
|
21
|
+
def initialize(depth:, width:, sqft:)
|
27
22
|
@depth = depth
|
28
23
|
@width = width
|
29
24
|
@sqft = sqft
|
30
|
-
@display = display
|
31
25
|
end
|
32
26
|
|
33
27
|
# @return [String]
|
@@ -35,17 +29,21 @@ module ExtraSpace
|
|
35
29
|
props = [
|
36
30
|
"depth=#{@depth.inspect}",
|
37
31
|
"width=#{@width.inspect}",
|
38
|
-
"sqft=#{@sqft.inspect}"
|
39
|
-
"display=#{@display.inspect}"
|
32
|
+
"sqft=#{@sqft.inspect}"
|
40
33
|
]
|
41
34
|
"#<#{self.class.name} #{props.join(' ')}>"
|
42
35
|
end
|
43
36
|
|
37
|
+
# @return [String] e.g. "10' × 10' (100 sqft)"
|
38
|
+
def text
|
39
|
+
"#{format('%g', @width)}' × #{format('%g', @depth)}' (#{@sqft} sqft)"
|
40
|
+
end
|
41
|
+
|
44
42
|
# @param data [Hash]
|
45
43
|
#
|
46
44
|
# @return [Dimensions]
|
47
45
|
def self.parse(data:)
|
48
|
-
new(depth: data['depth'], width: data['width'], sqft: data['squareFoot']
|
46
|
+
new(depth: data['depth'], width: data['width'], sqft: data['squareFoot'])
|
49
47
|
end
|
50
48
|
end
|
51
49
|
end
|
data/lib/extraspace/facility.rb
CHANGED
@@ -1,10 +1,20 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ExtraSpace
|
4
|
+
# A facility (address + geocode + prices) on extraspace.com.
|
5
|
+
#
|
4
6
|
# e.g. https://www.extraspace.com/storage/facilities/us/alabama/auburn/3264/
|
5
7
|
class Facility
|
6
8
|
SITEMAP_URL = 'https://www.extraspace.com/facility-sitemap.xml'
|
7
9
|
|
10
|
+
# @attribute [rw] id
|
11
|
+
# @return [String]
|
12
|
+
attr_accessor :id
|
13
|
+
|
14
|
+
# @attribute [rw] name
|
15
|
+
# @return [String]
|
16
|
+
attr_accessor :name
|
17
|
+
|
8
18
|
# @attribute [rw] address
|
9
19
|
# @return [Address]
|
10
20
|
attr_accessor :address
|
@@ -17,25 +27,6 @@ module ExtraSpace
|
|
17
27
|
# @return [Array<Price>]
|
18
28
|
attr_accessor :prices
|
19
29
|
|
20
|
-
# @param address [Address]
|
21
|
-
# @param geocode [Geocode]
|
22
|
-
# @param prices [Array<Price>]
|
23
|
-
def initialize(address:, geocode:, prices:)
|
24
|
-
@address = address
|
25
|
-
@geocode = geocode
|
26
|
-
@prices = prices
|
27
|
-
end
|
28
|
-
|
29
|
-
# @return [String]
|
30
|
-
def inspect
|
31
|
-
props = [
|
32
|
-
"address=#{@address.inspect}",
|
33
|
-
"geocode=#{@geocode.inspect}",
|
34
|
-
"prices=#{@prices.inspect}"
|
35
|
-
]
|
36
|
-
"#<#{self.class.name} #{props.join(' ')}>"
|
37
|
-
end
|
38
|
-
|
39
30
|
# @return [Sitemap]
|
40
31
|
def self.sitemap
|
41
32
|
Sitemap.fetch(url: SITEMAP_URL)
|
@@ -55,14 +46,60 @@ module ExtraSpace
|
|
55
46
|
# @return [Facility]
|
56
47
|
def self.parse(data:)
|
57
48
|
page_data = data.dig('props', 'pageProps', 'pageData', 'data')
|
58
|
-
|
49
|
+
store_data = page_data.dig('facilityData', 'data', 'store')
|
59
50
|
unit_classes = page_data.dig('unitClasses', 'data', 'unitClasses')
|
51
|
+
id = store_data['number']
|
52
|
+
name = store_data['name']
|
60
53
|
|
61
|
-
address = Address.parse(data:
|
62
|
-
geocode = Geocode.parse(data:
|
54
|
+
address = Address.parse(data: store_data['address'])
|
55
|
+
geocode = Geocode.parse(data: store_data['geocode'])
|
63
56
|
prices = unit_classes.map { |price_data| Price.parse(data: price_data) }
|
64
57
|
|
65
|
-
new(address:, geocode:, prices:)
|
58
|
+
new(id:, name:, address:, geocode:, prices:)
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.crawl
|
62
|
+
sitemap.links.each do |link|
|
63
|
+
url = link.loc
|
64
|
+
|
65
|
+
facility = fetch(url:)
|
66
|
+
puts facility.text
|
67
|
+
|
68
|
+
facility.prices.each do |price|
|
69
|
+
puts price.text
|
70
|
+
end
|
71
|
+
|
72
|
+
puts
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# @param id [String]
|
77
|
+
# @param name [String]
|
78
|
+
# @param address [Address]
|
79
|
+
# @param geocode [Geocode]
|
80
|
+
# @param prices [Array<Price>]
|
81
|
+
def initialize(id:, name:, address:, geocode:, prices:)
|
82
|
+
@id = id
|
83
|
+
@name = name
|
84
|
+
@address = address
|
85
|
+
@geocode = geocode
|
86
|
+
@prices = prices
|
87
|
+
end
|
88
|
+
|
89
|
+
# @return [String]
|
90
|
+
def inspect
|
91
|
+
props = [
|
92
|
+
"id=#{@id.inspect}",
|
93
|
+
"address=#{@address.inspect}",
|
94
|
+
"geocode=#{@geocode.inspect}",
|
95
|
+
"prices=#{@prices.inspect}"
|
96
|
+
]
|
97
|
+
"#<#{self.class.name} #{props.join(' ')}>"
|
98
|
+
end
|
99
|
+
|
100
|
+
# @return [String] e.g. "123 Main St, Springfield, IL 62701"
|
101
|
+
def text
|
102
|
+
"#{@id} | #{@name} | #{@address.text} | #{@geocode.text}"
|
66
103
|
end
|
67
104
|
end
|
68
105
|
end
|
data/lib/extraspace/geocode.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ExtraSpace
|
4
|
-
#
|
4
|
+
# The geocode (latitude + longitude) of a facility.
|
5
5
|
class Geocode
|
6
6
|
# @attribute [rw] latitude
|
7
7
|
# @return [Float]
|
@@ -27,6 +27,11 @@ module ExtraSpace
|
|
27
27
|
"#<#{self.class.name} #{props.join(' ')}>"
|
28
28
|
end
|
29
29
|
|
30
|
+
# @return [String]
|
31
|
+
def text
|
32
|
+
"#{@latitude},#{@longitude}"
|
33
|
+
end
|
34
|
+
|
30
35
|
# @param data [Hash]
|
31
36
|
#
|
32
37
|
# @return [Geocode]
|
data/lib/extraspace/price.rb
CHANGED
@@ -1,15 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ExtraSpace
|
4
|
-
#
|
4
|
+
# The price (id + dimensions + rate) for a facility
|
5
5
|
class Price
|
6
|
-
# @attribute [rw]
|
6
|
+
# @attribute [rw] id
|
7
7
|
# @return [String]
|
8
|
-
attr_accessor :
|
9
|
-
|
10
|
-
# @attribute [rw] availability
|
11
|
-
# @return [Availability]
|
12
|
-
attr_accessor :availability
|
8
|
+
attr_accessor :id
|
13
9
|
|
14
10
|
# @attribute [rw] dimensions
|
15
11
|
# @return [Dimensions]
|
@@ -19,13 +15,11 @@ module ExtraSpace
|
|
19
15
|
# @return [Rates]
|
20
16
|
attr_accessor :rates
|
21
17
|
|
22
|
-
# @param
|
23
|
-
# @param availability [Availability]
|
18
|
+
# @param id [String]
|
24
19
|
# @param dimensions [Dimensions]
|
25
20
|
# @param rates [Rates]
|
26
|
-
def initialize(
|
27
|
-
@
|
28
|
-
@availability = availability
|
21
|
+
def initialize(id:, dimensions:, rates:)
|
22
|
+
@id = id
|
29
23
|
@dimensions = dimensions
|
30
24
|
@rates = rates
|
31
25
|
end
|
@@ -33,24 +27,26 @@ module ExtraSpace
|
|
33
27
|
# @return [String]
|
34
28
|
def inspect
|
35
29
|
props = [
|
36
|
-
"
|
37
|
-
"availability=#{@availability.inspect}",
|
30
|
+
"id=#{@id.inspect}",
|
38
31
|
"dimensions=#{@dimensions.inspect}",
|
39
32
|
"rates=#{@rates.inspect}"
|
40
33
|
]
|
41
34
|
"#<#{self.class.name} #{props.join(' ')}>"
|
42
35
|
end
|
43
36
|
|
37
|
+
# @return [String] e.g. "123 | 5' × 5' (25 sqft) | $100 (street) / $90 (web)"
|
38
|
+
def text
|
39
|
+
"#{@id} | #{@dimensions.text} | #{@rates.text}"
|
40
|
+
end
|
41
|
+
|
44
42
|
# @param data [Hash]
|
45
43
|
#
|
46
44
|
# @return [Price]
|
47
45
|
def self.parse(data:)
|
48
|
-
availability = Availability.parse(data: data['availability'])
|
49
46
|
dimensions = Dimensions.parse(data: data['dimensions'])
|
50
47
|
rates = Rates.parse(data: data['rates'])
|
51
48
|
new(
|
52
|
-
|
53
|
-
availability: availability,
|
49
|
+
id: data['uid'],
|
54
50
|
dimensions: dimensions,
|
55
51
|
rates: rates
|
56
52
|
)
|
data/lib/extraspace/rates.rb
CHANGED
@@ -1,12 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ExtraSpace
|
4
|
-
#
|
4
|
+
# The rates (street + web) for a facility
|
5
5
|
class Rates
|
6
|
-
# @attribute [rw] nsc
|
7
|
-
# @return [Integer]
|
8
|
-
attr_accessor :nsc
|
9
|
-
|
10
6
|
# @attribute [rw] street
|
11
7
|
# @return [Integer]
|
12
8
|
attr_accessor :street
|
@@ -15,11 +11,9 @@ module ExtraSpace
|
|
15
11
|
# @return [Integer]
|
16
12
|
attr_accessor :web
|
17
13
|
|
18
|
-
# @param nsc [Integer]
|
19
14
|
# @param street [Integer]
|
20
15
|
# @param web [Integer]
|
21
|
-
def initialize(
|
22
|
-
@nsc = nsc
|
16
|
+
def initialize(street:, web:)
|
23
17
|
@street = street
|
24
18
|
@web = web
|
25
19
|
end
|
@@ -27,19 +21,22 @@ module ExtraSpace
|
|
27
21
|
# @return [String]
|
28
22
|
def inspect
|
29
23
|
props = [
|
30
|
-
"nsc=#{@nsc.inspect}",
|
31
24
|
"street=#{@street.inspect}",
|
32
25
|
"web=#{@web.inspect}"
|
33
26
|
]
|
34
27
|
"#<#{self.class.name} #{props.join(' ')}>"
|
35
28
|
end
|
36
29
|
|
30
|
+
# @return [String] e.g. "$80 (street) | $60 (web)"
|
31
|
+
def text
|
32
|
+
"$#{@street} (street) | $#{@web} (web)"
|
33
|
+
end
|
34
|
+
|
37
35
|
# @param data [Hash]
|
38
36
|
#
|
39
37
|
# @return [Rates]
|
40
38
|
def self.parse(data:)
|
41
39
|
new(
|
42
|
-
nsc: data['nsc'],
|
43
40
|
street: data['street'],
|
44
41
|
web: data['web']
|
45
42
|
)
|
data/lib/extraspace/sitemap.rb
CHANGED
data/lib/extraspace/version.rb
CHANGED
data/lib/extraspace.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: extraspace
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kevin Sylvestre
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-11-
|
11
|
+
date: 2024-11-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: http
|
@@ -52,6 +52,20 @@ dependencies:
|
|
52
52
|
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: optparse
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: zeitwerk
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -69,7 +83,8 @@ dependencies:
|
|
69
83
|
description: Uses HTTP.rb to scrape extraspace.com.
|
70
84
|
email:
|
71
85
|
- kevin@ksylvest.com
|
72
|
-
executables:
|
86
|
+
executables:
|
87
|
+
- extraspace
|
73
88
|
extensions: []
|
74
89
|
extra_rdoc_files: []
|
75
90
|
files:
|
@@ -77,9 +92,10 @@ files:
|
|
77
92
|
- README.md
|
78
93
|
- bin/console
|
79
94
|
- bin/setup
|
95
|
+
- exe/extraspace
|
80
96
|
- lib/extraspace.rb
|
81
97
|
- lib/extraspace/address.rb
|
82
|
-
- lib/extraspace/
|
98
|
+
- lib/extraspace/cli.rb
|
83
99
|
- lib/extraspace/crawler.rb
|
84
100
|
- lib/extraspace/dimensions.rb
|
85
101
|
- lib/extraspace/facility.rb
|
@@ -1,30 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module ExtraSpace
|
4
|
-
# e.g. https://www.extraspace.com/storage/facilities/us/alabama/auburn/3264/
|
5
|
-
class Availability
|
6
|
-
# @attribute [rw] available
|
7
|
-
# @return [String]
|
8
|
-
attr_accessor :available
|
9
|
-
|
10
|
-
# @param available [String]
|
11
|
-
def initialize(available:)
|
12
|
-
@available = available
|
13
|
-
end
|
14
|
-
|
15
|
-
# @return [String]
|
16
|
-
def inspect
|
17
|
-
props = [
|
18
|
-
"available=#{@available.inspect}"
|
19
|
-
]
|
20
|
-
"#<#{self.class.name} #{props.join(' ')}>"
|
21
|
-
end
|
22
|
-
|
23
|
-
# @param data [Hash]
|
24
|
-
#
|
25
|
-
# @return [Availability]
|
26
|
-
def self.parse(data:)
|
27
|
-
new(available: data['available'])
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|