extraspace 0.2.0 → 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 +5 -0
- data/lib/extraspace/cli.rb +58 -0
- data/lib/extraspace/crawler.rb +2 -2
- data/lib/extraspace/dimensions.rb +5 -0
- data/lib/extraspace/facility.rb +58 -23
- data/lib/extraspace/geocode.rb +5 -0
- data/lib/extraspace/price.rb +5 -0
- data/lib/extraspace/rates.rb +5 -0
- data/lib/extraspace/version.rb +1 -1
- data/lib/extraspace.rb +1 -0
- metadata +19 -2
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 "City: #{facility.address.city}"
|
28
|
-
puts "State: #{facility.address.state}"
|
29
|
-
puts "ZIP: #{facility.address.zip}"
|
30
|
-
puts "Latitude: #{facility.geocode.latitude}"
|
31
|
-
puts "Longitude: #{facility.geocode.longitude}"
|
32
|
-
puts
|
25
|
+
puts facility.text
|
33
26
|
|
34
27
|
facility.prices.each do |price|
|
35
|
-
puts
|
36
|
-
puts "Width: #{price.dimensions.width}"
|
37
|
-
puts "Depth: #{price.dimensions.depth}"
|
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
@@ -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
|
@@ -34,6 +34,11 @@ module ExtraSpace
|
|
34
34
|
"#<#{self.class.name} #{props.join(' ')}>"
|
35
35
|
end
|
36
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
|
+
|
37
42
|
# @param data [Hash]
|
38
43
|
#
|
39
44
|
# @return [Dimensions]
|
data/lib/extraspace/facility.rb
CHANGED
@@ -7,6 +7,14 @@ module ExtraSpace
|
|
7
7
|
class Facility
|
8
8
|
SITEMAP_URL = 'https://www.extraspace.com/facility-sitemap.xml'
|
9
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
|
+
|
10
18
|
# @attribute [rw] address
|
11
19
|
# @return [Address]
|
12
20
|
attr_accessor :address
|
@@ -19,25 +27,6 @@ module ExtraSpace
|
|
19
27
|
# @return [Array<Price>]
|
20
28
|
attr_accessor :prices
|
21
29
|
|
22
|
-
# @param address [Address]
|
23
|
-
# @param geocode [Geocode]
|
24
|
-
# @param prices [Array<Price>]
|
25
|
-
def initialize(address:, geocode:, prices:)
|
26
|
-
@address = address
|
27
|
-
@geocode = geocode
|
28
|
-
@prices = prices
|
29
|
-
end
|
30
|
-
|
31
|
-
# @return [String]
|
32
|
-
def inspect
|
33
|
-
props = [
|
34
|
-
"address=#{@address.inspect}",
|
35
|
-
"geocode=#{@geocode.inspect}",
|
36
|
-
"prices=#{@prices.inspect}"
|
37
|
-
]
|
38
|
-
"#<#{self.class.name} #{props.join(' ')}>"
|
39
|
-
end
|
40
|
-
|
41
30
|
# @return [Sitemap]
|
42
31
|
def self.sitemap
|
43
32
|
Sitemap.fetch(url: SITEMAP_URL)
|
@@ -57,14 +46,60 @@ module ExtraSpace
|
|
57
46
|
# @return [Facility]
|
58
47
|
def self.parse(data:)
|
59
48
|
page_data = data.dig('props', 'pageProps', 'pageData', 'data')
|
60
|
-
|
49
|
+
store_data = page_data.dig('facilityData', 'data', 'store')
|
61
50
|
unit_classes = page_data.dig('unitClasses', 'data', 'unitClasses')
|
51
|
+
id = store_data['number']
|
52
|
+
name = store_data['name']
|
62
53
|
|
63
|
-
address = Address.parse(data:
|
64
|
-
geocode = Geocode.parse(data:
|
54
|
+
address = Address.parse(data: store_data['address'])
|
55
|
+
geocode = Geocode.parse(data: store_data['geocode'])
|
65
56
|
prices = unit_classes.map { |price_data| Price.parse(data: price_data) }
|
66
57
|
|
67
|
-
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}"
|
68
103
|
end
|
69
104
|
end
|
70
105
|
end
|
data/lib/extraspace/geocode.rb
CHANGED
data/lib/extraspace/price.rb
CHANGED
@@ -34,6 +34,11 @@ module ExtraSpace
|
|
34
34
|
"#<#{self.class.name} #{props.join(' ')}>"
|
35
35
|
end
|
36
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
|
+
|
37
42
|
# @param data [Hash]
|
38
43
|
#
|
39
44
|
# @return [Price]
|
data/lib/extraspace/rates.rb
CHANGED
data/lib/extraspace/version.rb
CHANGED
data/lib/extraspace.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
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
|
@@ -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,8 +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
|
98
|
+
- lib/extraspace/cli.rb
|
82
99
|
- lib/extraspace/crawler.rb
|
83
100
|
- lib/extraspace/dimensions.rb
|
84
101
|
- lib/extraspace/facility.rb
|