rain_jackets 0.1.0 → 0.1.1
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 +5 -5
- data/lib/rain_jackets/cli.rb +46 -40
- data/lib/rain_jackets/jacket.rb +5 -5
- data/lib/rain_jackets/scraper.rb +26 -22
- data/lib/rain_jackets/version.rb +1 -1
- metadata +6 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: b14aafb20e54a79c1568eaa735a1f847d060f67b
|
|
4
|
+
data.tar.gz: 5a7767e72ed22a18855071717dfe4e803f29f4c1
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e374b6145f1b979c36002302d6bf100191ded907115da852d02a1617a50d3983f26a6126c208d82844e545756c9b0843177c8977806a15a7c75328e758508159
|
|
7
|
+
data.tar.gz: 980baf955e83bdcf702baccfd5309396270914792603183908a07faf0770bb1c04a5c4c76f0e4bc10f912bc06373ccc8e49913944216b7efb57590ff3190adb5
|
data/lib/rain_jackets/cli.rb
CHANGED
|
@@ -1,61 +1,67 @@
|
|
|
1
1
|
class RainJackets::CLI
|
|
2
2
|
attr_accessor :jackets
|
|
3
|
-
|
|
3
|
+
|
|
4
4
|
def initialize
|
|
5
|
+
# store all jacket instances in CLI's instance variable @all
|
|
5
6
|
@jackets = RainJackets::Scraper.initialize_jacket_objects
|
|
6
|
-
puts "
|
|
7
|
-
|
|
7
|
+
puts ""
|
|
8
|
+
puts "Welcome to the Best Women's Rain Jackets Rater!"
|
|
9
|
+
prompt_input
|
|
8
10
|
end
|
|
9
|
-
|
|
10
|
-
|
|
11
|
+
|
|
12
|
+
# Print instructions to screen and get user input
|
|
13
|
+
def prompt_input
|
|
11
14
|
puts "► What would you like to do?"
|
|
12
15
|
puts "► Enter: 'menu' to see all commands / 'exit' to exit program."
|
|
13
|
-
|
|
16
|
+
get_input
|
|
14
17
|
end
|
|
15
|
-
|
|
18
|
+
|
|
16
19
|
# Initiates call procedure to get and handle user input
|
|
17
|
-
def
|
|
20
|
+
def get_input
|
|
18
21
|
input = gets.chomp.strip
|
|
19
22
|
handle_input(input)
|
|
20
|
-
end
|
|
21
|
-
|
|
23
|
+
end
|
|
24
|
+
|
|
22
25
|
# Handles the user pint
|
|
23
|
-
def handle_input(input)
|
|
26
|
+
def handle_input(input)
|
|
24
27
|
if input == "all"
|
|
25
28
|
print_list_all
|
|
26
|
-
|
|
27
|
-
elsif (1..5).include?(input.to_i)
|
|
29
|
+
|
|
30
|
+
elsif (1..5).include?(input.to_i)
|
|
28
31
|
print_selected_jacket(input.to_i)
|
|
29
|
-
|
|
32
|
+
|
|
30
33
|
elsif ['wr', 'b', 'c', 'w', 'd', 'ps'].include?(input.downcase)
|
|
31
34
|
print_ratings(input.downcase)
|
|
32
|
-
|
|
35
|
+
|
|
33
36
|
elsif input == "menu"
|
|
34
37
|
print_menu
|
|
35
|
-
|
|
36
|
-
|
|
38
|
+
get_input
|
|
39
|
+
|
|
37
40
|
elsif input == "exit"
|
|
38
|
-
puts "Goodbye!
|
|
41
|
+
puts "Goodbye! Hope you found your favorite jacket!"
|
|
39
42
|
exit
|
|
40
|
-
|
|
41
|
-
else
|
|
42
|
-
puts "I don't understand that answer. Please try again"
|
|
43
|
+
|
|
44
|
+
else # Make sure that the program doesn't break with unexpected user input
|
|
45
|
+
puts "I don't understand that answer. Please try again!"
|
|
43
46
|
end
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
call #reinitiate call loop at the end of non-exited handle_input logic
|
|
47
|
+
|
|
48
|
+
prompt_input # Reinitiate get_input loop at the end of non-exited handle_input logic
|
|
47
49
|
end
|
|
48
|
-
|
|
50
|
+
|
|
51
|
+
# Display all best rain jackets
|
|
49
52
|
def print_list_all
|
|
50
|
-
puts "
|
|
53
|
+
puts ""
|
|
54
|
+
puts "----------------------- Best Women's Rain Jackets of 2019: -----------------------------"
|
|
51
55
|
@jackets.each_with_index do |jacket, i|
|
|
52
56
|
puts " #{(i+1).to_s}. #{jacket.name.split(" - ").first} — #{jacket.price} - #{jacket.overall_rating}/100 Overall Rating"
|
|
53
57
|
end
|
|
54
|
-
puts "
|
|
58
|
+
puts "-----------------------------------------------------------------------------------"
|
|
55
59
|
end
|
|
56
|
-
|
|
60
|
+
|
|
61
|
+
# Display details of chosen jacket
|
|
57
62
|
def print_selected_jacket(jacket_number)
|
|
58
63
|
jacket = @jackets[jacket_number - 1]
|
|
64
|
+
puts ""
|
|
59
65
|
puts "---------------- #{jacket_number}. #{jacket.name} ----------------"
|
|
60
66
|
puts "• Jacket Description: #{jacket.description}"
|
|
61
67
|
puts "• Price: #{jacket.price}"
|
|
@@ -72,8 +78,8 @@ class RainJackets::CLI
|
|
|
72
78
|
puts " - Packed Size: #{jacket.packed_size_rating}/10"
|
|
73
79
|
puts "-----------------------------------------------------------------"
|
|
74
80
|
end
|
|
75
|
-
|
|
76
|
-
#
|
|
81
|
+
|
|
82
|
+
# Convert user shortcut input to jacket attribute name as string
|
|
77
83
|
def read_rating_input(input)
|
|
78
84
|
if input == 'wr'
|
|
79
85
|
rating_category = "water_resistance_rating"
|
|
@@ -87,29 +93,29 @@ class RainJackets::CLI
|
|
|
87
93
|
rating_category = "durability_rating"
|
|
88
94
|
elsif input == 'ps'
|
|
89
95
|
rating_category = "packed_size_rating"
|
|
90
|
-
else
|
|
91
|
-
puts "Incorrect input. Please try again."
|
|
92
|
-
prompt_user_input
|
|
93
96
|
end
|
|
94
97
|
rating_category
|
|
95
98
|
end
|
|
96
|
-
|
|
99
|
+
|
|
100
|
+
# Display ranked list based on chosen rating category
|
|
97
101
|
def print_ratings(input)
|
|
98
102
|
rating_attribute = read_rating_input(input)
|
|
99
103
|
jackets_sorted_by_rating = @jackets.sort_by { |jacket| jacket.send(rating_attribute) }.reverse
|
|
100
|
-
|
|
104
|
+
|
|
101
105
|
# Convert rating attribute name to readable capitalized title
|
|
102
106
|
rating_category_name = rating_attribute.split('_').map(&:capitalize).join(' ')
|
|
103
|
-
|
|
107
|
+
|
|
108
|
+
puts ""
|
|
104
109
|
puts "-------------Best Jackets Ranked by #{rating_category_name} ------------------"
|
|
105
110
|
jackets_sorted_by_rating.each_with_index do |jacket, idx|
|
|
106
111
|
puts " #{idx + 1}. #{jacket.name} — #{jacket.send(rating_attribute)}/10"
|
|
107
112
|
end
|
|
108
|
-
puts "
|
|
113
|
+
puts "---------------------------------------------------------------------"
|
|
109
114
|
end
|
|
110
|
-
|
|
115
|
+
|
|
111
116
|
# Display all menu commands
|
|
112
|
-
def print_menu
|
|
117
|
+
def print_menu
|
|
118
|
+
puts ""
|
|
113
119
|
puts "========================== MENU ==============================="
|
|
114
120
|
puts "• List all jackets -> enter 'all'"
|
|
115
121
|
puts "• More information on specific jacket -> enter jacket #'1-5'"
|
|
@@ -119,7 +125,7 @@ class RainJackets::CLI
|
|
|
119
125
|
puts " 'c' — Comfort"
|
|
120
126
|
puts " 'w' — Weight"
|
|
121
127
|
puts " 'd' — Durability"
|
|
122
|
-
puts " 'ps' — Packed Size"
|
|
128
|
+
puts " 'ps' — Packed Size"
|
|
123
129
|
puts "• Exit program -> enter 'exit'"
|
|
124
130
|
puts "==============================================================="
|
|
125
131
|
puts "► What would you like to do?"
|
data/lib/rain_jackets/jacket.rb
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
class RainJackets::Jacket
|
|
2
2
|
attr_accessor :name, :url, :price, :description, :pros, :cons, :overall_rating
|
|
3
3
|
attr_accessor :water_resistance_rating, :breathability_rating, :comfort_rating, :weight_rating, :durability_rating, :packed_size_rating, :rating_category
|
|
4
|
-
|
|
4
|
+
|
|
5
5
|
@@all = []
|
|
6
|
-
|
|
7
|
-
#
|
|
6
|
+
|
|
7
|
+
# Add jacket instance into class variable @@all (array)
|
|
8
8
|
def initialize
|
|
9
9
|
@@all << self
|
|
10
10
|
end
|
|
11
|
-
|
|
11
|
+
|
|
12
12
|
def self.all # Class method to expose variable @@all
|
|
13
13
|
@@all
|
|
14
14
|
end
|
|
15
|
-
|
|
15
|
+
|
|
16
16
|
end
|
data/lib/rain_jackets/scraper.rb
CHANGED
|
@@ -3,11 +3,11 @@ class RainJackets::Scraper
|
|
|
3
3
|
def self.get_page
|
|
4
4
|
Nokogiri::HTML(open("https://www.outdoorgearlab.com/topics/clothing-womens/best-rain-jacket-womens"))
|
|
5
5
|
end
|
|
6
|
-
|
|
6
|
+
|
|
7
7
|
def self.scrape_jackets_table
|
|
8
8
|
self.get_page.css("div.content_table_xwide tr")
|
|
9
9
|
end
|
|
10
|
-
|
|
10
|
+
|
|
11
11
|
def self.initialize_jacket_objects
|
|
12
12
|
all_jackets = []
|
|
13
13
|
# Determines which row you're on, hence which property you're trying to populate
|
|
@@ -15,58 +15,62 @@ class RainJackets::Scraper
|
|
|
15
15
|
|
|
16
16
|
# Product name and URL
|
|
17
17
|
if tr_index == 0
|
|
18
|
-
# td_value = td_element
|
|
19
18
|
product_name_row = tr_element.css("div.compare_product_name")
|
|
20
|
-
|
|
19
|
+
|
|
21
20
|
product_name_row.each do |td_element|
|
|
21
|
+
# Initialize a new jacket instance
|
|
22
22
|
new_jacket = RainJackets::Jacket.new
|
|
23
23
|
new_jacket.name = td_element.text
|
|
24
24
|
new_jacket.url = "https://www.outdoorgearlab.com" + td_element.css("a").first.attributes["href"].value
|
|
25
25
|
all_jackets << new_jacket
|
|
26
26
|
end
|
|
27
|
-
|
|
27
|
+
|
|
28
28
|
# Product Price
|
|
29
29
|
elsif tr_index == 2
|
|
30
|
-
product_price_row = tr_element.css("td.compare_items span")
|
|
30
|
+
product_price_row = tr_element.css("td.compare_items span")
|
|
31
|
+
# Iterate through each td_element (column) and
|
|
32
|
+
# Populate each jacket's price attribute
|
|
33
|
+
product_price_row.each_with_index do |td_element, td_index|
|
|
31
34
|
td_value = td_element.text
|
|
32
35
|
all_jackets[td_index].price = td_value #price in string "$149.93"
|
|
33
36
|
end
|
|
34
|
-
|
|
37
|
+
|
|
35
38
|
# Overall rating
|
|
36
39
|
elsif tr_index == 3
|
|
37
40
|
overall_rating_row = tr_element.css("div.rating_score")
|
|
41
|
+
# Iterate through each rating_score (column) and
|
|
42
|
+
# Populate each jacket's overall_rating attribute
|
|
38
43
|
overall_rating_row.each_with_index do |rating_score, rating_row_index|
|
|
39
|
-
|
|
40
|
-
all_jackets[rating_row_index].overall_rating = rating_score.text
|
|
44
|
+
all_jackets[rating_row_index].overall_rating = rating_score.text #an integer
|
|
41
45
|
end
|
|
42
|
-
|
|
46
|
+
|
|
43
47
|
# Pros
|
|
44
48
|
elsif tr_index == 5
|
|
45
49
|
pros_row = tr_element.css("td.compare_items").each_with_index do |td_element, td_index|
|
|
46
50
|
td_value = td_element.text
|
|
47
51
|
all_jackets[td_index].pros = td_value
|
|
48
52
|
end
|
|
49
|
-
|
|
53
|
+
|
|
50
54
|
# Cons
|
|
51
55
|
elsif tr_index == 6
|
|
52
56
|
pros_row = tr_element.css("td.compare_items").each_with_index do |td_element, td_index|
|
|
53
57
|
td_value = td_element.text
|
|
54
58
|
all_jackets[td_index].cons = td_value
|
|
55
59
|
end
|
|
56
|
-
|
|
57
|
-
#
|
|
60
|
+
|
|
61
|
+
# Description
|
|
58
62
|
elsif tr_index == 7
|
|
59
63
|
description_row = tr_element.css("td.compare_items").each_with_index do |td_element, td_index|
|
|
60
64
|
td_value = td_element.text
|
|
61
65
|
all_jackets[td_index].description = td_value
|
|
62
66
|
end
|
|
63
|
-
|
|
64
|
-
# Rating categories (tr_index
|
|
67
|
+
|
|
68
|
+
# Rating categories (tr_index 9-14)
|
|
65
69
|
elsif (9..14).include?(tr_index)
|
|
66
70
|
tr_element.css("div.rating_score").each_with_index do |rating_score, rating_row_index|
|
|
67
71
|
jacket = all_jackets[rating_row_index]
|
|
68
72
|
rating_score = rating_score.text
|
|
69
|
-
|
|
73
|
+
|
|
70
74
|
if tr_index == 9
|
|
71
75
|
jacket.water_resistance_rating = rating_score
|
|
72
76
|
elsif tr_index == 10
|
|
@@ -80,12 +84,12 @@ class RainJackets::Scraper
|
|
|
80
84
|
elsif tr_index == 14
|
|
81
85
|
jacket.packed_size_rating = rating_score
|
|
82
86
|
end
|
|
83
|
-
|
|
87
|
+
|
|
84
88
|
all_jackets[rating_row_index] = jacket
|
|
85
89
|
end
|
|
86
|
-
end
|
|
87
|
-
end
|
|
88
|
-
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
# Returns an array of all 5 jacket instances
|
|
89
93
|
all_jackets
|
|
90
|
-
end
|
|
91
|
-
end
|
|
94
|
+
end
|
|
95
|
+
end
|
data/lib/rain_jackets/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rain_jackets
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- "'Jacqueline Lam'"
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2019-11-
|
|
11
|
+
date: 2019-11-03 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -66,7 +66,8 @@ dependencies:
|
|
|
66
66
|
- - ">="
|
|
67
67
|
- !ruby/object:Gem::Version
|
|
68
68
|
version: '0'
|
|
69
|
-
description: Get the details for 2019's best rain jackets from Outdoor Gear Lab.
|
|
69
|
+
description: Get the details for 2019's best rain jackets from Outdoor Gear Lab. Type
|
|
70
|
+
`gem install rain_jackets` to install gem and type`rain_jackets` to run.
|
|
70
71
|
email:
|
|
71
72
|
- "'jacqueline.karin.lam@gmail.com'"
|
|
72
73
|
executables:
|
|
@@ -99,7 +100,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
99
100
|
- !ruby/object:Gem::Version
|
|
100
101
|
version: '0'
|
|
101
102
|
requirements: []
|
|
102
|
-
|
|
103
|
+
rubyforge_project:
|
|
104
|
+
rubygems_version: 2.5.2.3
|
|
103
105
|
signing_key:
|
|
104
106
|
specification_version: 4
|
|
105
107
|
summary: CLI for best rain jackets
|