How can we call something like this <%= habit.current_level.missed_days %>
where we only call the missed_days
from the current_level
, instead of all the missed_days
in a habit (to just give an general idea of what we want).
For example if two boxes are checked, calling <%= habit.missed_days %>
in the habits index will show 2
and if eight boxes are checked it will show 8
, but the goal here is that even if 8 boxes are checked:
it will still only say 2
strikes in the index because we are trying to only count the missed_days
from the current level.
class Habit < ActiveRecord::Base
belongs_to :user
has_many :comments, as: :commentable
has_many :levels
serialize :committed, Array
validates :date_started, presence: true
before_save :current_level
acts_as_taggable
scope :private_submit, -> { where(private_submit: true) }
scope :public_submit, -> { where(private_submit: false) }
attr_accessor :missed_one, :missed_two, :missed_three
def save_with_current_level
self.levels.build
self.levels.build
self.levels.build
self.levels.build
self.levels.build
self.save
end
def self.committed_for_today
today_name = Date::DAYNAMES[Date.today.wday].downcase
ids = all.select { |h| h.committed.include? today_name }.map(&:id)
where(id: ids)
end
def current_level
return 0 unless date_started
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 } - self.missed_days
case n_days
when 0..9
1
when 10..24
2
when 25..44
3
when 45..69
4
when 70..99
5
else
"Mastery"
end
end
end
We have t.integer "missed_days", default: 0
in the levels & habits tables.
Much of missed_days
logic can be traced to its controller:
class DaysMissedController < ApplicationController
before_action :logged_in_user, only: [:create, :destroy]
def create
habit = Habit.find(params[:habit_id])
habit.missed_days = habit.missed_days + 1
habit.save!
level = habit.levels.find(params[:level_id])
level.missed_days = level.missed_days + 1
level.save!
head :ok # this returns an empty response with a 200 success status code
end
def destroy
habit = Habit.find(params[:habit_id])
habit.missed_days = habit.missed_days - 1
habit.save!
level = habit.levels.find(params[:level_id])
level.missed_days = level.missed_days - 1
level.save!
head :ok # this returns an empty response with a 200 success status code
end
end
The gist of it: https://gist.github.com/RallyWithGalli/c66dee6dfb9ab5d338c2
Thank you for your awesomeness!
It's a bit tricky to see exactly what you're trying to do but hopefully this will point you in the right direction:
It looks like you have a
current_level
method on theHabit
model but at the moment this returns the current level number and not the current level model.So maybe rename this method to
current_level_number
and then add acurrent_level
method like:then you should be able to do
habit.current_level.missed_days
to get the missed days for the current level.Also, be careful with your
current_level
method. It returns a number i.e. 1 to 5 in most cases but then returns a string "Mastery" under specific circumstances. I method that returns different types like this is likely to cause you trouble.A bit more detail: When you've created the habit it looks like you've set it up with 5 levels:
so these will be
levels[0]
,levels[1]
through tolevels[4]
In your
DaysMissedController
you're updating the days missed count on the habit itself and on one of the levels so I am assuming that it's thisdays_missed
count for the current level that you want to get hold of.Your
current_level
method returns a level number between 1 and 5 based onn_days
so when the user is on level 1 for the habit we wantlevels[0]
, for level 2,levels[1]
and so on.This is just an assumption since you didn't mention much of the associations, and I'm not even sure I understand what you want, but if what I am thinking is correct, i would think/assume it would go like this