I\'m creating a habit tracking app.
When a User creates a habit he will put in its :date_started
and which days he is :committed
to doing t
What exactly is committed
? I see:
t.text :committed
and
committed.map { |day| Date::DAYNAMES.index(day) }
That doesn't really make sense, I'm not sure how that works for you. It looks like you're storing multiple day names, if that's the case you should use an array of some sort (either strings or integers). Then you can set n_days
to simply committed.length
.
I would change that column to t.string :committed, array: true, default: []
or t.integer :committed, array: true, default: []
.
There are a lot of ways you can do this depending on your business logic. For example if you were unlocking certain privileges with each level you would want to handle it differently than if the level was simply to display a UI feature. Either way you would add a levels table that will hold the name of your level in a :name attribute. Then you would have a habit_level table that would be a join with the foreign key of the habit and the foreign key for the level. When ever you are updating the days you run a check to see if the days are of a certain number, and if they are, you create a record in the join table for the corresponding level and habit.
I believe your only problem is that you're storing the day names in lowercase in the committed
field, and then trying to match them with Date::DAYNAMES
, which has them in title case. Otherwise, the logic seems sound.
This should work:
committed_wdays = committed.map { |day| Date::DAYNAMES.index(day.titleize) }
n_days = ((date_started.to_date)..Date.today).count { |date| committed_wdays.include? date.wday }