Ruby on rails 从当前_水平开始计算天数?

Ruby on rails 从当前_水平开始计算天数?,ruby-on-rails,ruby,model-view-controller,Ruby On Rails,Ruby,Model View Controller,有5个级别 每个级别都有一定的天数,必须经过一定的天数,习惯才能升级到下一个级别(按n_天细分): 我们如何用类似于的东西从习惯索引中的当前水平调用n_天 例如,如果我们在第3级的50,则习惯指数中会显示第5天 习惯.rb class Habit < ActiveRecord::Base belongs_to :user has_many :comments, as: :commentable has_many :levels serialize :comm

有5个级别

每个级别都有一定的天数,必须经过一定的天数,习惯才能升级到下一个级别(按
n_天
细分):

我们如何用类似于
的东西从习惯索引中的当前水平调用
n_天

例如,如果我们在第3级的
50
,则习惯指数中会显示第5天

习惯.rb

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_strike
      levels[current_level - 1] # remember arrays indexes start at 0
    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
class Level < ActiveRecord::Base
  belongs_to :habit
end

它的要点:

在你的
当前的
方法中,你有两行逻辑,最终代表了
n天
的价值。如果要在该方法或case语句之外重用该值,则应将该值存储在实例变量中,或将逻辑移到另一个方法中。如果逻辑只对这个类重要,那么我可能会将它设置为私有方法

class Habit < ActiveRecord::Base
  # Existing code ... 

  private

  def committed_wdays
    committed.map do |day|    
      Date::DAYNAMES.index(day.titleize)
    end
  end

  def n_days
    ((date_started.to_date)..Date.today).count do |date| 
      committed_wdays.include? date.wday
    end - self.missed_days
  end
end
类习惯

私有方法可以进一步细化,但希望这能让您了解如何继续提取共享逻辑。

我认为您提供的代码比解释问题所需的代码还要多。我建议将问题细化到更具体一点。不过我想我明白了,我也会尽力提供一个答案。谢谢凯文!我将您的方法放在当前_级别(代替我的
=
代码)下,而不是放在private下。似乎有效。你能想到这个替代方案的任何负面影响吗?而且你当前的代码调用所有
n_天
,而不是只从当前级别调用,因此,例如,如果我养成了30天的习惯,我不想显示30天,我想显示5天,因为我们进入3级的时间是5天。我说得有道理吗?有可能吗?如果你还在研究这个问题,不包括
private
就可以了,但这是一种限制对方法的访问的方法,这些方法只能在类内部使用,不能从其他对象引用。好的,非常感谢您回复我@kevinthompson:)您知道一种方法,我可以直接调用当前级别的
中经过了多少天吗?这是你得到的一个艰难的飞跃吗?例如,调用
f.current_level
将获得准确的级别编号,因此1-5。调用
f.n_days
将给出自养成习惯以来已过去的总天数。调用
f.current\u level.n\u days
将给出未定义的方法
n\u days
create_table "habits", force: true do |t|
  t.integer  "missed_days",    default: 0
  t.text     "committed"
  t.integer  "days_lost",   default: 0
  t.datetime "date_started"
  t.string   "trigger"
  t.string   "target"
  t.string   "reward"
  t.boolean  "private_submit"
  t.integer  "user_id"
  t.datetime "created_at",                 null: false
  t.datetime "updated_at",                 null: false
  t.integer  "order"
end

add_index "habits", ["user_id", "created_at"], name: "index_habits_on_user_id_and_created_at"
add_index "habits", ["user_id"], name: "index_habits_on_user_id"

create_table "levels", force: true do |t|
  t.integer  "habit_id"
  t.integer  "days_lost",   default: 0
  t.integer  "missed_days",   default: 0
  t.integer  "current_level"
  t.datetime "created_at",                null: false
  t.datetime "updated_at",                null: false
end

add_index "levels", ["habit_id"], name: "index_levels_on_habit_id"
class Habit < ActiveRecord::Base
  # Existing code ... 

  private

  def committed_wdays
    committed.map do |day|    
      Date::DAYNAMES.index(day.titleize)
    end
  end

  def n_days
    ((date_started.to_date)..Date.today).count do |date| 
      committed_wdays.include? date.wday
    end - self.missed_days
  end
end