AnthonyGalli.com
AnthonyGalli.com

Reputation: 2866

Create conditional based upon current year when looping through records?

I want to show Date.current.year if there are no @past_challenges with a :deadline set for Date.current.year.

Controller

@past_challenges = current_user.challenges.order("deadline ASC").select{ |challenge| challenge.deadline < Date.current if challenge.deadline.present? }
@past_challenges_by_years = @past_challenges.group_by { |t| t.deadline.beginning_of_year }

Attempt

<% if @past_challenges_by_years[Date.today.year] ||= [ ] %>
  <h2>2016</h2>
<% end %>

The above didn't work because 2016 is duplicated. Once as part of the group_by and the other as part of the conditional. I only want the conditional to trigger if @past_challenges has no challenges with a t.date :deadline == Date.current.year. This will mean there should always be just one listing of the current year.

enter image description here

Upvotes: 0

Views: 45

Answers (1)

Kristj&#225;n
Kristj&#225;n

Reputation: 18803

I see two problems. One is that you're grouping your challenges by t.deadline.beginning_of_year, which is something like 2016-01-01 00:00:00 -0800, then pulling from your hash using Date.today.year, which is just 2016. You can use whichever of the two methods you prefer, you just have to be consistent. I'd recommend .year, since it's simpler and seems more semantic.

Meantime, @past_challenges_by_years[Date.today.year] is always going to be nil, and then you ||= [], leaving it always an empty array and leading to the second problem: empty arrays are truthy. Now your check always passes, and you always render 2016. You can fix the existing code by checking @past_challenges_by_years[Date.today.year].nil? to see if there's an entry at all, but you can remove some complexity from your view if you make some more guarantees about your hash:

@past_challenges_by_years = Hash.new { |hash, key| hash[key] = [] }
@past_challenges.each { |c| @past_challenges_by_years[c.deadline.year] << c }

Hash.new's block ensures that any key every looked up will be initialized with an empty array, so you won't have to worry about nils where you don't want them. Then in your view, you don't need to check whether there's a 2016 entry or special case the current year at all, you just render whichever years you want:

<%- 2016.downto(2010).each do |year| -%>
  <h2><%= year %></h2>
  <ul>
  <%- @past_challenges_by_year[year].each do |challenge| -%>
    <li><%= challenge.name %></li>
  <%- end -%>
  </ul>
<%- end -%>

Upvotes: 1

Related Questions