Lesson 1
Managing Product Reviews and Data Aggregation
Introduction

Hello, and welcome to the lesson! In this session, we’ll dive into managing product reviews and applying data aggregation in practice. We’ll start with a simple setup task to establish our foundation, then build toward a more complex solution involving data aggregation. Let’s get started!

Starter Task: Methods and Their Definitions

For our starter task, we’ll set up the basic operations needed to manage product reviews. Here are the essential methods we’ll implement:

  • add_review(product_id, review_id, review_text, rating) — Adds a review for a specified product_id. If a review with review_id already exists, it updates the review. Returns true if it adds or updates a review successfully; otherwise, it fails if the rating is not between 1 and 5.
  • get_review(product_id, review_id) — Returns the details of a specific review (review_text, rating, and flagged status) for a given product_id. If the review or product doesn’t exist, returns nil.
  • delete_review(product_id, review_id) — Deletes a specific review under the given product_id. Returns true if successfully deleted, false otherwise.
Implementing Basic Review Management

To start, we’ll create a ReviewManager class that manages all product reviews within a hash structure, @products, where each key is a product_id, and each value is a collection of reviews associated with that product.

Ruby
1class ReviewManager 2 def initialize 3 @products = {} 4 end 5end

In this initial setup, the initialize method creates an empty hash, @products, to store all product reviews in the system.

Adding and Updating Reviews with add_review

The first method, add_review, will allow us to add a new review or update an existing one for a specific product. This method ensures that each review contains a valid rating between 1 and 5.

Ruby
1def add_review(product_id, review_id, review_text, rating) 2 return false if rating < 1 || rating > 5 3 4 @products[product_id] ||= {} 5 @products[product_id][review_id] = { text: review_text, rating: rating, flagged: false } 6 true 7end

In add_review, we start by validating the rating to ensure it’s between 1 and 5. If the rating is valid, we initialize the product in @products (if it doesn’t already exist) and then add or update the review under the specified review_id. This method returns true if the review is successfully added or updated.

Retrieving Review Details with get_review

The get_review method retrieves a specific review’s details for a given product. It returns the review text, rating, and flagged status.

Ruby
1def get_review(product_id, review_id) 2 return nil unless @products[product_id] && @products[product_id][review_id] 3 4 review = @products[product_id][review_id] 5 { text: review[:text], rating: review[:rating], flagged: review[:flagged] } 6end

In get_review, we first check if the product and review exist. If they do, we return a hash containing the review’s text, rating, and flagged status. The flagged status indicates whether the review has been marked as inappropriate. If the review or product does not exist, the method returns nil.

Deleting a Review with delete_review

The delete_review method removes a specific review for a given product. If no reviews remain for that product, the product is also removed from @products.

Ruby
1def delete_review(product_id, review_id) 2 return false unless @products[product_id] && @products[product_id][review_id] 3 4 @products[product_id].delete(review_id) 5 @products.delete(product_id) if @products[product_id].empty? 6 true 7end

In delete_review, we first confirm that the product and review exist. If they do, we delete the review. If this deletion results in an empty set of reviews for the product, we remove the product from @products. This method returns true if the review was successfully deleted.

New Task: Advanced Functions and Data Aggregation

With our basic review management system in place, we’ll now introduce two additional methods to handle more advanced operations, such as flagging inappropriate reviews and aggregating review data for a specific product.

Here are the new methods we’ll add:

  • flag_review(product_id, review_id) — Flags a specific review as inappropriate for a given product. Returns true if the review was successfully flagged, false otherwise.
  • aggregate_reviews(product_id) — Aggregates review data for a product, providing statistics like the total number of reviews, flagged reviews, average rating, and review texts excluding flagged ones. If no reviews are available, it returns nil.
Flagging Inappropriate Reviews with flag_review

We’ll add functionality to mark specific reviews as inappropriate using the flag_review method.

Ruby
1def flag_review(product_id, review_id) 2 if @products[product_id] && @products[product_id][review_id] 3 @products[product_id][review_id][:flagged] = true 4 return true 5 end 6 false 7end

In flag_review, we check if the product and review exist in @products. If they do, we set the flagged attribute of the review to true, allowing inappropriate reviews to be tracked separately. This method returns true if the review is successfully flagged.

Aggregating Review Data with aggregate_reviews

Our final method, aggregate_reviews, compiles review data for a specified product, including statistics on total reviews, flagged reviews, average rating, and non-flagged review texts.

Ruby
1def aggregate_reviews(product_id) 2 return nil unless @products[product_id] 3 4 total_reviews = @products[product_id].size 5 flagged_reviews = 0 6 total_rating = 0 7 review_texts = [] 8 9 @products[product_id].each_value do |review| 10 if review[:flagged] 11 flagged_reviews += 1 12 else 13 total_rating += review[:rating] 14 review_texts << review[:text] 15 end 16 end 17 18 average_rating = total_reviews == flagged_reviews ? 0 : total_rating.to_f / (total_reviews - flagged_reviews) 19 20 # The review_texts array stores the texts of only non-flagged reviews. 21 { 22 total_reviews: total_reviews, 23 flagged_reviews: flagged_reviews, 24 average_rating: average_rating, 25 review_texts: review_texts 26 } 27end

In aggregate_reviews, we start by ensuring the product exists. Then, we calculate the total number of reviews, the count of flagged reviews, and the cumulative rating for non-flagged reviews. We then determine the average rating, excluding flagged reviews. The review_texts array stores the texts of only non-flagged reviews. If all reviews are flagged, the average rating defaults to zero. The method returns a hash with the aggregated statistics.

Conclusion

Great job! In this lesson, we implemented essential methods for managing product reviews, starting with adding, retrieving, and deleting reviews. We then extended our functionality to flag reviews and aggregate review data. This gradual approach shows how to enhance features incrementally and handle data aggregation tasks efficiently.

Try practicing similar tasks to solidify your understanding. Keep coding, and see you in the next lesson!

Enjoy this lesson? Now it's time to practice with Cosmo!
Practice is how you turn knowledge into actual skills.