Reputation: 13388
Using Rails 6. Here's a piece that I wrote just to display number of stars. Obviously I am disgusted by my own code. How would you refactor?
# application_helper.rb
module ApplicationHelper
def show_star_rating(rating)
zero_star_icon_name = "star"
full_star_icon_name = "star_fill"
half_star_icon_name = "star_lefthalf_fill"
total_stars = []
round_by_half = (rating * 2).round / 2.0
(round_by_half.to_i).times { total_stars << full_star_icon_name }
if round_by_half - round_by_half.to_i == 0.5
total_stars << half_star_icon_name
end
if total_stars.size != 5
(5 - total_stars.size).times { total_stars << zero_star_icon_name }
end
total_stars
end
end
# show.html.erb
<% show_star_rating(agent_review.rating).each do |star| %>
<i class="f7-icons"><%= star %></i>
<% end %>
Upvotes: 0
Views: 326
Reputation: 841
The way I would implement show_star_rating
:
def show_star_rating(rating)
zero_star_icon_name = "star"
full_star_icon_name = "star_fill"
half_star_icon_name = "star_lefthalf_fill"
rating_round_point5 = (rating * 2).round / 2.0
(1..5).map do |i|
next(full_star_icon_name) if i <= rating_round_point5
next(half_star_icon_name) if rating_round_point5 + 0.5 == i
zero_star_icon_name
end
end
Upvotes: 1
Reputation: 11050
You can make use of the Array.new
, passing in the maximum number of stars you want to show, and defaulting all the stars to empty. Then, you can fill
in the number of full stars you need. Then, finally, thanks to Numeric
's divmod
returning either 0
or 1
for the number of half stars you need, you make one more pass and fill
in the number of half stars you need:
module StarHelper
EMPTY_STAR_ICON = 'star'.freeze
FULL_STAR_ICON = 'star_fill'.freeze
HALF_STAR_ICON = 'star_lefthalf_fill'.freeze
def full_and_half_star_count(rating)
(rating * 2).round.divmod(2)
end
def stars(rating, max_stars: 5)
full_stars, half_stars = full_and_half_star_count(rating)
Array.new(max_stars, EMPTY_STAR_ICON).
fill(FULL_STAR_ICON, 0, full_stars).
fill(HALF_STAR_ICON, full_stars, half_stars)
end
end
Upvotes: 3