rain_jackets 0.1.3 → 0.1.4

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
  SHA1:
3
- metadata.gz: 774adb1e37745af58e1de5b0b6301f92c8f054a3
4
- data.tar.gz: b0a41bdcd8ad0638ed0e8b4d18e566ee3289b65e
3
+ metadata.gz: 2db2b5acf891f0b2bcea3c4d438dd3b5efd5bc6a
4
+ data.tar.gz: 6bd0e9787540efb11ecd0836fc1636dee16c2969
5
5
  SHA512:
6
- metadata.gz: bf4010a22558961890686629a9ff8aff699f96d25704d8256c51051fe4ddb4420248c56b19dcde0c3ecc8161dc6ed53e3545a74317c4da3b06210dbecbaf22a9
7
- data.tar.gz: 7a4a8d4428965b87648bc1c71fee479e5ee8f3d2300363c5264a2f345a6e262b95c4304fc6703aa465b26dd0680d01fce4e06b6b3ccb4bbeafbb1eb941a79102
6
+ metadata.gz: 4f64bb9034469c3d03326231de09023988beda0096457449b3412355cab4d99f1c139d0e369f35173ad959055e7f590dd55e467e4c7f0fe09adb2471a82c61c0
7
+ data.tar.gz: 0644436574c221a574e4cab7cad3f745ab4444c6f64ebde78332b9bb681905cb13d6f671580bc82422d5e3917dcb01f01ab627fc967b910f25d4b31f390d3a83
@@ -2,4 +2,5 @@
2
2
 
3
3
  require_relative '../config/environment/'
4
4
 
5
+ # Initiates call procedure to start CLI app
5
6
  RainJackets::CLI.new.call
@@ -1,7 +1,9 @@
1
+ # All the required code to initialize the environment
2
+
1
3
  ### REQUIRED GEMS ###
2
4
  require 'nokogiri'
3
5
  require 'open-uri'
4
- require 'pry'
6
+ # require 'pry'
5
7
 
6
8
  ### REQUIRED FILES ###
7
9
  require_relative '../lib/rain_jackets/version'
@@ -2,23 +2,25 @@ class RainJackets::CLI
2
2
  attr_accessor :jackets
3
3
 
4
4
  def call
5
- # store all jacket instances in CLI's instance variable @all
6
- @jackets = RainJackets::Scraper.initialize_jacket_objects
5
+ # Calls Scraper class method that will return array of all jacket objects
6
+ # Store all Jacket instances in CLI's instance variable @jackets
7
+ RainJackets::Scraper.initialize_jacket_objects
8
+ @jackets = RainJackets::Jacket.all
9
+ # Greet user with text input
7
10
  puts ""
8
11
  puts "Welcome to the Best Women's Rain Jackets Rater!"
9
12
  prompt_input
10
13
  end
11
14
 
12
- # Print instructions to screen and get user input
15
+ # Print instructions to screen and prompts user for input
13
16
  def prompt_input
14
17
  puts "► What would you like to do?"
15
18
  puts "► Enter: 'menu' to see all commands / 'exit' to exit program."
16
19
  get_input
17
20
  end
18
21
 
19
- # Initiates call procedure to get and handle user input
20
22
  def get_input
21
- input = gets.chomp.strip
23
+ input = gets.strip.downcase
22
24
  handle_input(input)
23
25
  end
24
26
 
@@ -30,8 +32,8 @@ class RainJackets::CLI
30
32
  elsif (1..5).include?(input.to_i)
31
33
  print_selected_jacket(input.to_i)
32
34
 
33
- elsif ['wr', 'b', 'c', 'w', 'd', 'ps'].include?(input.downcase)
34
- print_ratings(input.downcase)
35
+ elsif ['wr', 'b', 'c', 'w', 'd', 'ps'].include?(input)
36
+ print_ratings(input)
35
37
 
36
38
  elsif input == "menu"
37
39
  print_menu
@@ -42,10 +44,11 @@ class RainJackets::CLI
42
44
  exit
43
45
 
44
46
  else # Make sure that the program doesn't break with unexpected user input
47
+ puts ""
45
48
  puts "I don't understand that answer. Please try again!"
46
49
  end
47
50
 
48
- prompt_input # Reinitiate get_input loop at the end of non-exited handle_input logic
51
+ prompt_input # Reinitiate program loop at the end of non-exited handle_input logic
49
52
  end
50
53
 
51
54
  # Display all best rain jackets
@@ -53,7 +56,8 @@ class RainJackets::CLI
53
56
  puts ""
54
57
  puts "----------------------- Best Women's Rain Jackets of 2019: -----------------------------"
55
58
  @jackets.each_with_index do |jacket, i|
56
- puts " #{(i+1).to_s}. #{jacket.name.split(" - ").first} — #{jacket.price} - #{jacket.overall_rating}/100 Overall Rating"
59
+ ranking = (i+1).to_s
60
+ puts " #{ranking}. #{jacket.name.split(" - ").first} — #{jacket.price} - #{jacket.overall_rating}/100 Overall Rating"
57
61
  end
58
62
  puts "-----------------------------------------------------------------------------------"
59
63
  end
@@ -79,20 +83,22 @@ class RainJackets::CLI
79
83
  puts "-----------------------------------------------------------------"
80
84
  end
81
85
 
82
- # Convert user shortcut input to jacket attribute name as string
86
+ # Convert user input to jacket attribute name string
83
87
  def read_rating_input(input)
84
- if input == 'wr'
85
- rating_category = "water_resistance_rating"
86
- elsif input == 'b'
87
- rating_category = "breathability_rating"
88
- elsif input == 'c'
89
- rating_category = "comfort_rating"
90
- elsif input == 'w'
91
- rating_category = "weight_rating"
92
- elsif input == 'd'
93
- rating_category = "durability_rating"
94
- elsif input == 'ps'
95
- rating_category = "packed_size_rating"
88
+ # case statement to run multiple conditions against input value
89
+ case input
90
+ when 'wr'
91
+ rating_category = "water_resistance_rating"
92
+ when 'b'
93
+ rating_category = "breathability_rating"
94
+ when 'c'
95
+ rating_category = "comfort_rating"
96
+ when 'w'
97
+ rating_category = "weight_rating"
98
+ when 'd'
99
+ rating_category = "durability_rating"
100
+ when 'ps'
101
+ rating_category = "packed_size_rating"
96
102
  end
97
103
  rating_category
98
104
  end
@@ -100,7 +106,9 @@ class RainJackets::CLI
100
106
  # Display ranked list based on chosen rating category
101
107
  def print_ratings(input)
102
108
  rating_attribute = read_rating_input(input)
103
- jackets_sorted_by_rating = @jackets.sort_by { |jacket| jacket.send(rating_attribute) }.reverse
109
+ # Dynamically access specified attribute reader and
110
+ # Sort all jacket instances in descending order of the rating attribute's value
111
+ jackets_sorted_by_rating = @jackets.sort_by { |jacket| jacket.send(rating_attribute)}.reverse
104
112
 
105
113
  # Convert rating attribute name to readable capitalized title
106
114
  rating_category_name = rating_attribute.split('_').map(&:capitalize).join(' ')
@@ -113,7 +121,7 @@ class RainJackets::CLI
113
121
  puts "---------------------------------------------------------------------"
114
122
  end
115
123
 
116
- # Display all menu commands
124
+ # Display all menu commands/ Define input interface
117
125
  def print_menu
118
126
  puts ""
119
127
  puts "========================== MENU ==============================="
@@ -4,13 +4,13 @@ class RainJackets::Jacket
4
4
 
5
5
  @@all = []
6
6
 
7
- # Add jacket instance into class variable @@all (array)
8
- def initialize
9
- @@all << self
7
+ # Set class method @@all to equate jackets array created by Scraper
8
+ def self.all=(jackets)
9
+ @@all = jackets.uniq
10
10
  end
11
11
 
12
- def self.all # Class method to expose variable @@all
12
+ # Class method to expose variable @@all
13
+ def self.all
13
14
  @@all
14
15
  end
15
-
16
- end
16
+ end
@@ -1,41 +1,53 @@
1
1
  class RainJackets::Scraper
2
2
 
3
+ # Take HTML string returned by open-uri's open method
4
+ # and convert it into a NodeSet
3
5
  def self.get_page
4
6
  Nokogiri::HTML(open("https://www.outdoorgearlab.com/topics/clothing-womens/best-rain-jacket-womens"))
5
7
  end
6
8
 
7
9
  def self.scrape_jackets_table
10
+ # Use CSS selector to grab all HTML elements that contain a table
11
+ # return array of Nokogiri XML elements representing
12
+ # table described on scraped webpage
8
13
  self.get_page.css("div.content_table_xwide tr")
9
14
  end
10
15
 
16
+ # Instantiate jacket objects and assign attributes to each instance
11
17
  def self.initialize_jacket_objects
12
18
  all_jackets = []
19
+
13
20
  # Determines which row you're on, hence which property you're trying to populate
21
+ # Iterate through collection of table rows
22
+
14
23
  scrape_jackets_table.each_with_index do |tr_element, tr_index|
15
24
 
16
- # Product name and URL
25
+ # Scrape product Name and URL
17
26
  if tr_index == 0
27
+ # Grab the element that contains our desired data
18
28
  product_name_row = tr_element.css("div.compare_product_name")
19
29
 
30
+ # Iterate through each of td element and instantiate new jacket
20
31
  product_name_row.each do |td_element|
21
- # Initialize a new jacket instance
32
+ # Create a new Jacket instance out of each aray element
33
+ # instantiating Jacket objects and giving each jacket object the correct attributes
22
34
  new_jacket = RainJackets::Jacket.new
23
- new_jacket.name = td_element.text
35
+ new_jacket.name = td_element.text #access text content inside an element scraped by Nokogiri
24
36
  new_jacket.url = "https://www.outdoorgearlab.com" + td_element.css("a").first.attributes["href"].value
25
37
  all_jackets << new_jacket
26
38
  end
27
39
 
28
- # Product Price
40
+ # Scrape Price
29
41
  elsif tr_index == 2
30
42
  product_price_row = tr_element.css("td.compare_items span")
31
43
  # Iterate through each td_element (column) and
32
44
  # Populate each jacket's price attribute
33
45
  product_price_row.each_with_index do |td_element, td_index|
34
46
  td_value = td_element.text
35
- all_jackets[td_index].price = td_value #price in string "$149.93"
47
+ all_jackets[td_index].price = td_value # Price in string "$149.93"
36
48
  end
37
49
 
38
- # Overall rating
50
+ # Scrape Overall Rating
39
51
  elsif tr_index == 3
40
52
  overall_rating_row = tr_element.css("div.rating_score")
41
53
  # Iterate through each rating_score (column) and
@@ -44,28 +56,28 @@ class RainJackets::Scraper
44
56
  all_jackets[rating_row_index].overall_rating = rating_score.text #an integer
45
57
  end
46
58
 
47
- # Pros
59
+ # Scrape Pros
48
60
  elsif tr_index == 5
49
61
  pros_row = tr_element.css("td.compare_items").each_with_index do |td_element, td_index|
50
62
  td_value = td_element.text
51
63
  all_jackets[td_index].pros = td_value
52
64
  end
53
65
 
54
- # Cons
66
+ # Scrape Cons
55
67
  elsif tr_index == 6
56
68
  pros_row = tr_element.css("td.compare_items").each_with_index do |td_element, td_index|
57
69
  td_value = td_element.text
58
70
  all_jackets[td_index].cons = td_value
59
71
  end
60
72
 
61
- # Description
73
+ # Scrape Description
62
74
  elsif tr_index == 7
63
75
  description_row = tr_element.css("td.compare_items").each_with_index do |td_element, td_index|
64
76
  td_value = td_element.text
65
77
  all_jackets[td_index].description = td_value
66
78
  end
67
79
 
68
- # Rating categories (tr_index 9-14)
80
+ # Scrape rating categories if tr_index is between 9-14
69
81
  elsif (9..14).include?(tr_index)
70
82
  tr_element.css("div.rating_score").each_with_index do |rating_score, rating_row_index|
71
83
  jacket = all_jackets[rating_row_index]
@@ -84,12 +96,10 @@ class RainJackets::Scraper
84
96
  elsif tr_index == 14
85
97
  jacket.packed_size_rating = rating_score
86
98
  end
87
-
88
- all_jackets[rating_row_index] = jacket
89
99
  end
90
100
  end
91
101
  end
92
- # Returns an array of all 5 jacket instances
93
- all_jackets
102
+ # Store all_jackets array in Jacket class variable @@all
103
+ RainJackets::Jacket.all = all_jackets
94
104
  end
95
105
  end
@@ -1,3 +1,3 @@
1
1
  module RainJackets
2
- VERSION = "0.1.3"
2
+ VERSION = "0.1.4"
3
3
  end
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.3
4
+ version: 0.1.4
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-03 00:00:00.000000000 Z
11
+ date: 2019-11-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler