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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c428e33759133c5e280f2dfb72c99c04e71ee4c64f96f6b9ba2228cd5fdc033e
4
- data.tar.gz: a2be67b968e35c3fa689583d00cacf92608cf74906d8b854c52f9333059a1857
3
+ metadata.gz: e31518705b665cfcff3914a8553164f1463a3c66140cb41ea14be9154abf44fa
4
+ data.tar.gz: bf86b8674cf0557e239b286acaca2f77d1688bd3f431434ad15914db9624a143
5
5
  SHA512:
6
- metadata.gz: c66f9b36b6ee74d375a791c57a9f0712efe65c65a3aa5b6c7bc146779e22cb2f10cb5e2f176eea2b6430a7255620f0fa218d4bcefa015b39723c35653821ea15
7
- data.tar.gz: d0f1f59b09c2f6d86baad0819ab63f5ca68491e9ccfc9895c0f5f43ccb69418130dc898ed1087ad9d1580397ad9270256f8253d61982c092969e1bbde27214dc
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 "Street: #{facility.address.street}"
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 "ID: #{price.id}"
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
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'extraspace'
5
+
6
+ cli = ExtraSpace::CLI.new
7
+ cli.parse
@@ -41,6 +41,11 @@ module ExtraSpace
41
41
  "#<#{self.class.name} #{props.join(' ')}>"
42
42
  end
43
43
 
44
+ # @return [String]
45
+ def text
46
+ "#{street}, #{city}, #{state} #{zip}"
47
+ end
48
+
44
49
  # @param data [Hash]
45
50
  #
46
51
  # @return [Address]
@@ -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
@@ -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]
@@ -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
- facility_data = page_data.dig('facilityData', 'data')
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: facility_data['store']['address'])
64
- geocode = Geocode.parse(data: facility_data['store']['geocode'])
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
@@ -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]
@@ -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]
@@ -27,6 +27,11 @@ module ExtraSpace
27
27
  "#<#{self.class.name} #{props.join(' ')}>"
28
28
  end
29
29
 
30
+ # @return [String] e.g. "$80 (street) | $60 (web)"
31
+ def text
32
+ "$#{@street} (street) | $#{@web} (web)"
33
+ end
34
+
30
35
  # @param data [Hash]
31
36
  #
32
37
  # @return [Rates]
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ExtraSpace
4
- VERSION = '0.2.0'
4
+ VERSION = '0.3.0'
5
5
  end
data/lib/extraspace.rb CHANGED
@@ -6,6 +6,7 @@ require 'zeitwerk'
6
6
 
7
7
  loader = Zeitwerk::Loader.for_gem
8
8
  loader.inflector.inflect 'extraspace' => 'ExtraSpace'
9
+ loader.inflector.inflect 'cli' => 'CLI'
9
10
  loader.setup
10
11
 
11
12
  module ExtraSpace
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.2.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