如果用户核对错过的3天,如何重新启动等级?

时间:2015-03-18 23:29:16

标签: ruby-on-rails ruby model-view-controller model integer

我正在创建一个用户跟踪他们的积极习惯的应用。

为了让追踪积极的习惯变得更有趣,我将其分解为等级,特别是5个等级。

每个级别都有一定的:committed天与之关联(case n_days)。

如果用户在_form <%= f.check_box :missedone %>中关闭了3x框,则应重新启动。我们如何才能为:missedone:missedtwo:missedthree:missedfour:missedfive开展此工作?

:committed天是用户说他会做出积极习惯的日子。

例如,我{J}运行周一至周五:committed。因此,如果我错过了周一至周五的一天,那么错过的只会被检查。

class Habit < ActiveRecord::Base
    belongs_to :user
    before_save :set_level
    acts_as_taggable
    serialize :committed, Array

  def self.comitted_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 levels
            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 }

  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

private
    def set_level
     self.level = levels
    end 
end

习惯/ _form.html.erb

  <label> Missed: </label>
  <div>
  <label> Level 1: </label>
  <%= f.check_box :missedone %>
  <%= f.check_box :missedone %>
  <%= f.check_box :missedone %>
  </div>
  <div>
  <label> Level 2: </label>
  <%= f.check_box :missedtwo %>
  <%= f.check_box :missedtwo %>
  <%= f.check_box :missedtwo %>
  </div>
  <div>
  <label> Level 3: </label>
  <%= f.check_box :missedthree %>
  <%= f.check_box :missedthree %>
  <%= f.check_box :missedthree %>
  </div>
  <div>
  <label> Level 4: </label>
  <%= f.check_box :missedfour %>
  <%= f.check_box :missedfour %>
  <%= f.check_box :missedfour %>
  </div>
  <div>
  <label> Level 5: </label>
  <%= f.check_box :missedfive %>
  <%= f.check_box :missedfive %>
  <%= f.check_box :missedfive %>
  </div>

habits_controller.rb

    class HabitsController < ApplicationController
      before_action :set_habit, only: [:show, :edit, :update, :destroy]
      before_action :logged_in_user, only: [:create, :destroy]

      def index
        if params[:tag]
          @habits = Habit.tagged_with(params[:tag])
        else
          @habits = Habit.all.order("date_started DESC")
          @habits = current_user.habits
        end
      end

    private

        def habit_params
          params.require(:habit).permit(:missedone, :missedtwo, :missedthree, :missedfour, :missedfive, :left, :level, :date_started, :trigger, :target, :positive, :negative, :tag_list, :committed => [])
        end
    end

_create_habits.rb

class CreateHabits < ActiveRecord::Migration
  def change
    create_table :habits do |t|
      t.integer :missedone
      t.integer :missedtwo
      t.integer :missedthree
      t.integer :missedfour
      t.integer :missedfive
      t.integer :level #broken down via n_days
      t.text :committed
      t.datetime :date_started
      t.string :trigger
      t.string :target
      t.string :positive
      t.string :negative
      t.references :user, index: true

      t.timestamps null: false
    end
    add_foreign_key :habits, :users
    add_index :habits, [:user_id, :created_at]
  end
end

我一直在试图弄清楚这个答案,所以任何帮助都会非常受欢迎。

1 个答案:

答案 0 :(得分:0)

很抱歉这样说,但我不明白这样做的意义。你最终会在模型中找到与状态相关的逻辑(实际上它就是你现在拥有的,以及导致所有问题的原因)。

无论如何,要回答你的问题,首先是你做错了(我认为无论如何)。为了使它工作,你必须重新开始一些事情。

在你的情况下,我会选择state_machine gem。这样你就可以摆脱状态转换逻辑。你必须在你的课程中映射那些,但它会以这种方式更具可读性和可维护性。

使用状态机,您可能会根据您的习惯映射不同的状态,例如level0,[...],level5master,然后只定义转换条件。< / p>

例如,假设您的模型中有committed_countmissed_count个字段。


level0level1的条件是:

committed_count > level1_go_up_const

level1level0的条件是:

missed_count&gt; level1_go_down_const`


等等其他级别。是的,您应该将这些数字提取为常数,甚至更好地作为变量提取(因此用户可以在设置中对其进行自定义。

在每次改变时,你的习惯应该试图降低它的状态。如果那是不可能的(没有足够的错过天数)那么它会试图推进它的状态。如果那是不可能的(没有足够的承诺天数),那么就不会发生与状态相关的事情。另一方面,如果这是可能的,那么它就会进入状态。并且每个状态更改都应该将已提交和未命中的值更改为零,以便下一个/上一个状态可以跟踪它自己的限制并且表现得足够好。

通过这种方式,你可以 - 当基础工作时 - 在其上添加一些糖,而不会做一些magic不可读(对于任何其他人)操作,switch / cases和mystic if语句,以便制作其他你现在将需要或需要的东西 - 比如检查过去几天是否错过,如果他们没有被检查为既未错过,也没有为某些活动类型添加某种周计划(可能应由用户编辑)。等等。

为了实现这一目标,你还应该考虑引入更多小而有意义的私人方法,因为在不久的将来你不会记得发生了什么。