A simple way to efficiently calculate and represent average data in Rails
Tags: ruby, rails
Published: 2023-02-07 21:47:29

I'm working on a project and I encountered a scenario where I need to calculate the average marks of students and create a simple visualization indicator to represent the calculated average. After a few iterations, I found this can be accomplished through a simple implementation and subsequent refactoring of the code.

**Scenario**
Let's say you have a `Student` model `studen.rb` and `AcadmicReport` model `academic_report.rb` . You want to show student's average marks in student show view, but the marks are an attribute of the academic_report model.
Initially, you may write a method to calculate the average marks, which can be done by iterating through the student's academic reports and summing the marks. You can then divide the sum by the number of academic reports to get the average marks.

```
# student.rb
def average_marks(marks)   
    marks.sum / marks.length 
end
```

Next, you can create a method to assign the stars for the calculated average marks. This can be done through a simple case a statement that assigns a certain number of stars based on the range of the average marks.

```
# academic_reports_helper.rb
def 
    stars_for_average_marks(average) 
    case average 
    when 0..40 
        stars = 1 
    when 41..60 
        stars = 2
    when 61..80 
        stars = 3 
    when 81..90 
        stars = 4 
    else stars = 5 
    end 

    "⭐ " * stars
end
```

Finally, you can render the stars in your student show view using the two methods.

```
# views/students/show.html.erb
<%= stars_for_average_marks(average_marks(@student.academic_reports.map { |report| report.marks })) %>
```

**Refactor**
While this implementation works, it can be further optimized and refactored. For example, you can add a method in the Student model to calculate the average marks and then call that method in the view. This helps keep your code clean and organized and makes it easier to maintain and understand when you visit it later.

```
# in the Student model 
def average_academic_marks   
    academic_reports.sum(:marks) / academic_reports.count 
end  

# in the student show view 
<%= stars_for_average_marks(@student.average_academic_marks) %>
```

As you see, Rails helps calculate the average marks of students (or a model you work with), and create a simple visualization indicator, and it can be done through a simple implementation. By refactoring the code and moving the calculation to the Student model, you can improve the readability and maintainability of your code.

**Bounce**
In addition to the average_academic_marks method, we can also calculate the average marks in percentage form. This is easily done with the use of the average_academic_marks method. Simply create a new method called average_academic_marks_percentage and add the necessary calculation as below:
```
# student.rb
def average_academic_marks_percentage
    (average_academic_marks * 100 / 100).to_s + '%' # 100 is the maximum marks 
end
```

With this new method, we now have the ability to access both the average marks in numerical form as well as in percentage form. This adds another layer of insight and information that can be used to better understand and analyze student performance. And it is a nice feature, teachers love it.
In conclusion, by refactoring our initial code and moving the calculation logic into the Student model, we have made our code cleaner, more maintainable, and easily extendable for future needs.

And as usual, Happy Coding 😀 💻