I was thinking that when a user checked a checkbox, the page would automatically trigger an AJAX call and update the Level model (calling either the create or destroy action). The user wouldn't have to submit the form manually.
class Level < ActiveRecord::Base
belongs_to :habit
end
The point is that if a user misses a day of doing their good habit they should check off the missed box. For every day that they miss they must make up for it before advancing to the next level in the positive habit formation process.
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 }
actual_days = n_days - 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
You can see the +1 increment here for missing a day. How can we save this via AJAX?
class DaysMissedController < ApplicationController
before_action :logged_in_user, only: [:create, :destroy]
def create
level = Habit.find(params[:habit_id]).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
level = Habit.find(params[:habit_id]).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
Config file
resources :habits do
resources :comments
resources :levels do
# we'll use this route to increment and decrement the missed days
resources :days_missed, only: [:create, :destroy]
end
end
Here is a visual from the habits _form:
habits _form
<label> Missed: </label>
<% @habit.levels.each_with_index do |level, index| %>
<p>
<label> Level <%= index + 1 %>: </label>
<%= f.check_box :missed_one, checked: (level.missed_days > 0) %>
<%= f.check_box :missed_two, checked: (level.missed_days > 1) %>
<%= f.check_box :missed_three, checked: (level.missed_days > 2) %>
</p>
<% end %>
Thank you for your expertise!