extraspace 0.1.0 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4d0f31dad347795d2fb0a8cbd14b3c6452fc8c8dfea0f9b66639bc4c1bf1c433
4
- data.tar.gz: 35cedca68983cab7e29c76abc7c8c83d617dad6c2ef881bbd13ecced436fd89d
3
+ metadata.gz: b2d656b5fbca3894562492b6a8c3e90c97a4c785cf88d6ff7c2c65c380a5ba8e
4
+ data.tar.gz: c564ac28246067bfb3d843070aa8ea3dcaa0898e12161e15c7570439cd8d4907
5
5
  SHA512:
6
- metadata.gz: e56ad3839e7a9f5a11b8298e7977c518590aade51b78a7248c201b03027b35b697ef792e311e76b797d1d6aa51d00e996d753651ff66e2fb5e00b74d2c8ab86c
7
- data.tar.gz: 5bb15f6c216c19d628f2179dd4dafe714804ee50d9142d72039d7fba0e68a5ad7ceaaa29e54259868a3ad0f53be9e0d9c677ce207ced6a5730471a2ac0439f13
6
+ metadata.gz: 503b60e74410c4fe5cf0db8644382555cf0ddb8343790e5eed69d61c7b8d5e494be3cdbd55097fee3454f555f2bd030722b704906384da65d020e688252ad46a
7
+ data.tar.gz: d48d92e05c00b065619738803344b79254ecb29cec4e9d461a47709169c1125864d278f07ce421647b17d2e6f83efdb09c9a102fe393766edab8d5aa457639db
data/README.md CHANGED
@@ -17,22 +17,26 @@ gem install extrapsace
17
17
  ```ruby
18
18
  require 'extraspace'
19
19
 
20
- URL = 'https://www.extraspace.com/storage/facilities/us/alabama/auburn/3264/'
21
- facility = ExtraSpace::Facility.fetch(url: URL)
22
-
23
- puts "Line 1: #{facility.address.line1}"
24
- puts "Line 2: #{facility.address.line2}"
25
- puts "City: #{facility.address.city}"
26
- puts "State: #{facility.address.state}"
27
- puts "ZIP: #{facility.address.zip}"
28
- puts "Latitude: #{facility.geocode.latitude}"
29
- puts "Longitude: #{facility.geocode.longitude}"
30
- puts
31
-
32
- facility.prices.each do |price|
33
- puts "UID: #{price.uid}"
34
- puts "Dimensions: #{price.dimensions.display}"
35
- puts "Rates: $#{price.rates.street} (street) / $#{price.rates.web} (web)"
20
+ sitemap = ExtraSpace::Facility.sitemap
21
+ sitemap.links.each do |link|
22
+ url = link.loc
23
+
24
+ facility = ExtraSpace::Facility.fetch(url:)
25
+
26
+ puts "Line 1: #{facility.address.line1}"
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}"
36
33
  puts
34
+
35
+ facility.prices.each do |price|
36
+ puts "UID: #{price.uid}"
37
+ puts "Dimensions: #{price.dimensions.display}"
38
+ puts "Rates: $#{price.rates.street} (street) / $#{price.rates.web} (web)"
39
+ puts
40
+ end
37
41
  end
38
42
  ```
@@ -26,9 +26,8 @@ module ExtraSpace
26
26
  # @param line1 [String]
27
27
  # @param line2 [String]
28
28
  # @param city [String]
29
- # @param state_abbreviation [String]
30
- # @param state_name [String]
31
- # @param postal_code [String]
29
+ # @param state [String]
30
+ # @param zip [String]
32
31
  def initialize(line1:, line2:, city:, state:, zip:)
33
32
  @line1 = line1
34
33
  @line2 = line2
@@ -37,6 +36,7 @@ module ExtraSpace
37
36
  @zip = zip
38
37
  end
39
38
 
39
+ # @return [String]
40
40
  def inspect
41
41
  props = [
42
42
  "line1=#{@line1.inspect}",
@@ -7,7 +7,7 @@ module ExtraSpace
7
7
  # @return [String]
8
8
  attr_accessor :available
9
9
 
10
- # @param uid [String]
10
+ # @param available [String]
11
11
  def initialize(available:)
12
12
  @available = available
13
13
  end
@@ -22,7 +22,7 @@ module ExtraSpace
22
22
 
23
23
  # @param data [Hash]
24
24
  #
25
- # @return [Address]
25
+ # @return [Availability]
26
26
  def self.parse(data:)
27
27
  new(available: data['available'])
28
28
  end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ExtraSpace
4
+ # Used to fetch and parse either HTML or XML via a URL.
5
+ class Crawler
6
+ # Raised for unexpected HTTP responses.
7
+ class FetchError < StandardError
8
+ # @param url [String]
9
+ # @param response [HTTP::Response]
10
+ def initialize(url:, response:)
11
+ super("url=#{url} status=#{response.status.inspect} body=#{response.body.inspect}")
12
+ end
13
+ end
14
+
15
+ # @param url [String]
16
+ # @raise [FetchError]
17
+ # @return [Nokogiri::HTML::Document]
18
+ def self.html(url:)
19
+ new.html(url:)
20
+ end
21
+
22
+ # @param url [String]
23
+ # @raise [FetchError]
24
+ # @return [Nokogiri::XML::Document]
25
+ def self.xml(url:)
26
+ new.xml(url:)
27
+ end
28
+
29
+ # @param url [String]
30
+ # @return [HTTP::Response]
31
+ def fetch(url:)
32
+ response = HTTP.get(url)
33
+ raise FetchError(url:, response: response.flush) unless response.status.ok?
34
+
35
+ response
36
+ end
37
+
38
+ # @param url [String]
39
+ # @raise [FetchError]
40
+ # @return [Nokogiri::XML::Document]
41
+ def html(url:)
42
+ Nokogiri::HTML(String(fetch(url:).body))
43
+ end
44
+
45
+ # @param url [String]
46
+ # @raise [FetchError]
47
+ # @return [Nokogiri::XML::Document]
48
+ def xml(url:)
49
+ Nokogiri::XML(String(fetch(url:).body))
50
+ end
51
+ end
52
+ end
@@ -19,7 +19,10 @@ module ExtraSpace
19
19
  # @return [String]
20
20
  attr_accessor :display
21
21
 
22
- # @param uid [String]
22
+ # @param depth [Integer]
23
+ # @param width [Integer]
24
+ # @param sqft [Integer]
25
+ # @param display [String]
23
26
  def initialize(depth:, width:, sqft:, display:)
24
27
  @depth = depth
25
28
  @width = width
@@ -40,7 +43,7 @@ module ExtraSpace
40
43
 
41
44
  # @param data [Hash]
42
45
  #
43
- # @return [Address]
46
+ # @return [Dimensions]
44
47
  def self.parse(data:)
45
48
  new(depth: data['depth'], width: data['width'], sqft: data['squareFoot'], display: data['display'])
46
49
  end
@@ -3,6 +3,8 @@
3
3
  module ExtraSpace
4
4
  # e.g. https://www.extraspace.com/storage/facilities/us/alabama/auburn/3264/
5
5
  class Facility
6
+ SITEMAP_URL = 'https://www.extraspace.com/facility-sitemap.xml'
7
+
6
8
  # @attribute [rw] address
7
9
  # @return [Address]
8
10
  attr_accessor :address
@@ -24,6 +26,7 @@ module ExtraSpace
24
26
  @prices = prices
25
27
  end
26
28
 
29
+ # @return [String]
27
30
  def inspect
28
31
  props = [
29
32
  "address=#{@address.inspect}",
@@ -33,15 +36,18 @@ module ExtraSpace
33
36
  "#<#{self.class.name} #{props.join(' ')}>"
34
37
  end
35
38
 
39
+ # @return [Sitemap]
40
+ def self.sitemap
41
+ Sitemap.fetch(url: SITEMAP_URL)
42
+ end
43
+
36
44
  # @param url [String]
37
45
  #
38
46
  # @return [Facility]
39
47
  def self.fetch(url:)
40
- response = HTTP.get(url)
41
- document = Nokogiri::HTML(String(response.body))
48
+ document = Crawler.html(url:)
42
49
  data = JSON.parse(document.at('#__NEXT_DATA__').text)
43
-
44
- parse(data: data)
50
+ parse(data:)
45
51
  end
46
52
 
47
53
  # @param data [Hash]
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ExtraSpace
4
+ # A link in a sitemap.
5
+ class Link
6
+ # @attribute [rw] loc
7
+ # @return [String]
8
+ attr_accessor :loc
9
+
10
+ # @attribute [rw] lastmod
11
+ # @return [Time]
12
+ attr_accessor :lastmod
13
+
14
+ # @param loc [String]
15
+ # @param lastmod [String]
16
+ def initialize(loc:, lastmod:)
17
+ @loc = loc
18
+ @lastmod = Time.parse(lastmod)
19
+ end
20
+
21
+ # @return [String]
22
+ def inspect
23
+ "#<#{self.class.name} loc=#{@loc.inspect} lastmod=#{@lastmod.inspect}>"
24
+ end
25
+ end
26
+ end
@@ -43,7 +43,7 @@ module ExtraSpace
43
43
 
44
44
  # @param data [Hash]
45
45
  #
46
- # @return [Address]
46
+ # @return [Price]
47
47
  def self.parse(data:)
48
48
  availability = Availability.parse(data: data['availability'])
49
49
  dimensions = Dimensions.parse(data: data['dimensions'])
@@ -15,7 +15,9 @@ module ExtraSpace
15
15
  # @return [Integer]
16
16
  attr_accessor :web
17
17
 
18
- # @param uid [String]
18
+ # @param nsc [Integer]
19
+ # @param street [Integer]
20
+ # @param web [Integer]
19
21
  def initialize(nsc:, street:, web:)
20
22
  @nsc = nsc
21
23
  @street = street
@@ -34,7 +36,7 @@ module ExtraSpace
34
36
 
35
37
  # @param data [Hash]
36
38
  #
37
- # @return [Address]
39
+ # @return [Rates]
38
40
  def self.parse(data:)
39
41
  new(
40
42
  nsc: data['nsc'],
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ExtraSpace
4
+ # e.g. https://www.extraspace.com/facility-sitemap.xml
5
+ class Sitemap
6
+ # @attribute [rw] links
7
+ # @return [Array<Link>]
8
+ attr_accessor :links
9
+
10
+ # @param document [NokoGiri::XML::Document]
11
+ #
12
+ # @return [Sitemap]
13
+ def self.parse(document:)
14
+ links = document.xpath('//xmlns:url').map do |url|
15
+ loc = url.at_xpath('xmlns:loc')&.text
16
+ lastmod = url.at_xpath('xmlns:lastmod')&.text
17
+ Link.new(loc:, lastmod:)
18
+ end
19
+
20
+ new(links: links)
21
+ end
22
+
23
+ # @param url [String]
24
+ #
25
+ # @return [Sitemap]
26
+ def self.fetch(url:)
27
+ document = Crawler.xml(url:)
28
+ parse(document:)
29
+ end
30
+
31
+ # @param links [Array<Link>]
32
+ def initialize(links:)
33
+ @links = links
34
+ end
35
+
36
+ # @return [String]
37
+ def inspect
38
+ "#<#{self.class.name} links=#{@links.inspect}>"
39
+ end
40
+ end
41
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ExtraSpace
4
- VERSION = '0.1.0'
4
+ VERSION = '0.1.2'
5
5
  end
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.1.0
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kevin Sylvestre
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-11-20 00:00:00.000000000 Z
11
+ date: 2024-11-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: http
@@ -80,11 +80,14 @@ files:
80
80
  - lib/extraspace.rb
81
81
  - lib/extraspace/address.rb
82
82
  - lib/extraspace/availability.rb
83
+ - lib/extraspace/crawler.rb
83
84
  - lib/extraspace/dimensions.rb
84
85
  - lib/extraspace/facility.rb
85
86
  - lib/extraspace/geocode.rb
87
+ - lib/extraspace/link.rb
86
88
  - lib/extraspace/price.rb
87
89
  - lib/extraspace/rates.rb
90
+ - lib/extraspace/sitemap.rb
88
91
  - lib/extraspace/version.rb
89
92
  homepage: https://github.com/ksylvest/extraspace
90
93
  licenses:
@@ -94,7 +97,7 @@ metadata:
94
97
  homepage_uri: https://github.com/ksylvest/extraspace
95
98
  source_code_uri: https://github.com/ksylvest/extraspace
96
99
  changelog_uri: https://github.com/ksylvest/extraspace
97
- post_install_message:
100
+ post_install_message:
98
101
  rdoc_options: []
99
102
  require_paths:
100
103
  - lib
@@ -109,8 +112,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
109
112
  - !ruby/object:Gem::Version
110
113
  version: '0'
111
114
  requirements: []
112
- rubygems_version: 3.5.22
113
- signing_key:
115
+ rubygems_version: 3.5.23
116
+ signing_key:
114
117
  specification_version: 4
115
118
  summary: A crawler for ExtraSpace.
116
119
  test_files: []