AnthonyGalli.com AnthonyGalli.com - 7 months ago 17
Ruby Question

How to make integer into array of dates?

If a user creates a challenge with

days_challenge: 5
&
committed: ["mon", "tue", "wed", "thu", "fri"]
then how can we create an array of dates from
date_started: "2016-04-20"
until the last day of the challenge using a model method called
dates_challenged
?

create_table "challenges", force: true do |t|
t.string "action"
t.date "date_started"
t.text "committed", default: "---\n- sun\n- mon\n- tue\n- wed\n- thu\n- fri\n- sat\n"
t.integer "days_challenged"
end


The array would look something like this:
["2016-04-20", "2016-04-21", "2016-04-22", "2016-04-25", "2016-04-26"]


class Challenge < ActiveRecord::Base
serialize :committed, Array

def dates_challenged
# Not sure if a model method is enough or if I'd have to migrate a new column
end

def committed_wdays
committed.map do |day|
Date::ABBR_DAYNAMES.index(day.titleize)
end
end

def days_left_challenged
def days_done_challenged
((date_started.to_date)..Date.yesterday).count do |date|
committed_wdays.include? date.wday
end
end
if self.days_done_challenged >= self.days_challenged
0
else
self.days_challenged - ((date_started.to_date)..Date.yesterday).count do |date|
committed_wdays.include? date.wday
end
end
end
end


To clarify, I'm trying to make a model method so I could do
@challenge.dates_challenged
in a view where I can then iterate over the array of dates.

Answer

This is what I came up with - there are still some issues - I think it will blow up if committed is empty, but it's nice and concise:

def dates_challenged
  date = date_started-1
  days_challenge.times.map { date = find_next(date) }
end

private
def find_next(date)
  break if committed.include? Date::ABBR_DAYNAMES[date.wday].downcase while date = date.next
  date
end