title: How to make level.missed_days = habit.missed_days? [Gist Included]
body: <p>I'm trying to gamify the forming of good habits. </p>
  
  <p>When the user creates a new habit there are 5 levels before achieving "mastery"! Each level has a certain amount of days associated with it (shown in <strong>habits.rb</strong> <code>n_days</code>).</p>
  
  <p>This is where I'm stuck: Despite checking the <code>missed_days</code> box for <code>:level</code> 1 in the <code>:habit</code> _form, the console showed <code>missed_days: 0</code> for <code>Habit.find(1)</code> yet <code>missed_days: 1</code> for <code>Level.find(1)</code>. </p>
  
  <p>Missing a day is a bad thing because the idea is if you miss a day (represented by checking a box), a day is added back into your current_level (through the days_missed controller), in other words only completed days count toward completing a level.</p>
  
  <p>How can we get it so that how ever many <code>:missed_days</code> are in <code>:level</code> will also be the same integer in <code>:habit</code>?</p>
  
  <p>Habits <code>has_many</code> levels.</p>
  
  <p><img src="https://i.stack.imgur.com/2fGNI.png" alt="enter image description here"></p>
  
  <p><strong>habits _form</strong></p>
  
  <pre><code>  &lt;label id="&lt;%= @habit.id %&gt;" class="habit-id"&gt; Missed: &lt;/label&gt;
      &lt;% @habit.levels.each_with_index do |level, index| %&gt;
        &lt;p&gt;
          &lt;label id="&lt;%= level.id %&gt;" class="level-id"&gt; Level &lt;%= index + 1 %&gt;: &lt;/label&gt;
          &lt;%= check_box_tag nil, true, level.missed_days &gt; 0, {class: "habit-check"} %&gt;
          &lt;%= check_box_tag nil, true, level.missed_days &gt; 1, {class: "habit-check"} %&gt;
          &lt;%= check_box_tag nil, true, level.missed_days &gt; 2, {class: "habit-check"} %&gt;
        &lt;/p&gt;
      &lt;% end %&gt;
  &lt;% end %&gt;
  </code></pre>
  
  <p><code>habit-check</code> is in regards to <strong>habit.js</strong></p>
  
  <pre><code>$(document).ready(function()
  {
    $(".habit-check").change(function()
    {
      habit = $(this).parent().siblings(".habit-id").first().attr("id");
      level = $(this).siblings(".level-id").first().attr("id");
      if($(this).is(":checked"))
      {
         $.ajax(
         {
           url: "/habits/" + habit + "/levels/" + level + "/days_missed",
           method: "POST"
         });
      }
      else
      {
         $.ajax(
         {
           url: "/habits/" + habit + "/levels/" + level + "/days_missed/1",
           method: "DELETE"
         });
      }
    });
  });
  </code></pre>
  
  <p>This is what happens in the <strong>terminal</strong> when I click a checkbox:</p>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="false" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-html lang-html prettyprint-override"><code>Started POST "/habits/2/levels/6/days_missed" for 127.0.0.1 at 2015-04-28 13:57:20 -0400
  Processing by DaysMissedController#create as */*
    Parameters: {"habit_id"=&gt;"2", "level_id"=&gt;"6"}
    User Load (0.2ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1  [["id", 1]]
    Habit Load (0.2ms)  SELECT "habits".* FROM "habits" WHERE "habits"."user_id" = ?  [["user_id", 1]]
    Habit Load (0.4ms)  SELECT "habits".* FROM "habits"
    ActsAsTaggableOn::Tag Load (0.2ms)  SELECT "tags".* FROM "tags" WHERE (LOWER(name) = LOWER('ingrain'))
    Habit Load (0.2ms)  SELECT  "habits".* FROM "habits" WHERE "habits"."id" = ? LIMIT 1  [["id", 2]]
    Level Load (0.1ms)  SELECT  "levels".* FROM "levels" WHERE "levels"."habit_id" = ? AND "levels"."id" = ? LIMIT 1  [["habit_id", 2], ["id", 6]]
     (0.1ms)  begin transaction
    SQL (0.3ms)  UPDATE "levels" SET "missed_days" = ?, "updated_at" = ? WHERE "levels"."id" = ?  [["missed_days", 1], ["updated_at", "2015-04-28 17:57:20.960578"], ["id", 6]]
     (3.0ms)  commit transaction
  Completed 200 OK in 27ms (ActiveRecord: 4.7ms)</code></pre>
  </div>
  </div>
  </p>
  
  <p><strong>habits.rb</strong></p>
  
  <pre><code>class Habit &lt; 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, -&gt; { where(private_submit: true) }
      scope :public_submit, -&gt; { 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(&amp;: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
  </code></pre>
  
  <p><strong>days_missed_controller.rb</strong></p>
  
  <pre><code>class DaysMissedController &lt; 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
  </code></pre>
  
  <p><strong>routes.rb</strong></p>
  
  <pre><code>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
  </code></pre>
  
  <p>Here's the gist of it: <a href="https://gist.github.com/RallyWithGalli/c66dee6dfb9ab5d338c2" rel="nofollow noreferrer">https://gist.github.com/RallyWithGalli/c66dee6dfb9ab5d338c2</a></p>