如何整合:错过的日子:养成习惯的日子.rb?

我们如何整合t.integer :missedt.text :committed这样做

  1. 当用户检查他时:missed 3 :committed日期在:level他必须重新启动:level

  2. 对于每一个:missed一天,他检查,额外的:committed一天被添加回到:level以便他必须在推进之前弥补?

在达到"Mastery"之前,每个习惯都有5个等级!

 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 

我猜我们必须要区分:missed:missed这里,取决于它指的是什么级别。

习惯/ _form.html.erb

   

habits_controller.rb

 class HabitsController  []) end end 

_create_habits.rb

 class CreateHabits < ActiveRecord::Migration def change create_table :habits do |t| t.integer :missed t.integer :level 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 

:committed完美,但现在:missed任何目的。 请帮我添加适当的逻辑进行整合:missed :committed

非常感谢您的参与!

UPDATE

@ Dimitry_N的答案并没有达到这个问题的1)或2),就像我试图让它发挥作用一样。 也许你会更好地融入他的逻辑。 有了他的回答我也得到了这个错误: 如何修复level.rb与:承诺的日子?

你应该打破这个问题,因为在一个问题上要求很多。 Dimitry_N似乎在正确的轨道上,但你现在需要将一些逻辑添加到关卡模型中。 如果您想了解详细信息,请与我聊天。

我认为程序设计必须稍加重新评估。 我认为levelsdays应该是单独的模型,其中包含levelmissed列(遵循SRP的概念,如他在评论中提到的@dgilperez)。 因此,我们最终得到四个模型: UserHabitLevelDay ,具有以下关联:

  • 用户has_many :habitshas_many :habitshas_many :levels
  • 习惯belongs_to:userhas_many :levelshas_many :days, through: :levels #for being able to access Habit.find(*).days
  • 级别belongs_to :userbelongs_to :habithas_many :days
  • Daybelongs_to :levelbelongs_to :habit

通过这些关联,您可以创建具有嵌套属性的表单。 有一个很棒的RailCast解释嵌套表格 。

 <%= form_for @habit do |habit| %> <% 5.times.each_with_index do |number, index| %> 

Level <%= index + 1 %>

<%= habit.fields_for :levels do |level| %> <%= level.fields_for :days do |day| %> <%= day.label :missed %> <%= day.check_box :missed %>
<% end %> <% end %> <% end %> <%= habit.submit "submit" %> <% end %>

而且“magic”发生在habits_controller ,看起来像这样:

 class HabitsController < ApplicationController ... def new @habit = @user.habits.new @level = @habit.levels.new 3.times { @level.days.build } end def create @habit = @user.habits.new(habit_params) @levels = @habit.levels if @habit.save @habit.evaluate(@user) redirect_to ... else ... end end ... private def habit_params params.require(:habit).permit( :user_id, levels_attributes:[ :passed, days_attributes:[ :missed,:level_id]]) end ... end 

注意nested strong params@habit.evalulate(@user)方法,我将在下面显示,以及3 3.times { @level.days.build }调用,它在视图中构建嵌套表单的字段。

habit.evauate(user)方法:在保存新Habit后调用此方法。 评估属性,并将错过的天数和级别的ID分别附加到用户的missed_daysmissed_levels属性。 逻辑有点笨拙,因为你将一个数组附加到另​​一个数组,所以你可能会提出更高效的东西。 与此同时:

  def evaluate(user) levels.each { |level| level.evaluate } user.missed_levels << levels.where(passed: false).ids user.missed_days << days.where(missed: true).ids user.save end 

请注意对level.evaluate的调用,如下所示:

  def evaluate if days.where(missed: true ).count == 3 update_attributes(passed: false) else update_attributes(passed: true) end end 

架构看起来像这样:

  create_table "days", force: true do |t| t.integer "level_id" t.integer "habit_id" t.boolean "missed", default: false end create_table "habits", force: true do |t| ... t.integer "user_id" ... end create_table "levels", force: true do |t| t.integer "user_id" t.integer "habit_id" t.boolean "passed", default: false end create_table "users", force: true do |t| ... t.string "name" t.text "missed_days" #serialize to Array #serialize to Array in model t.text "missed_levels" #serialize to Array in model ... end 

并且不要忘记使用accepts_nested_attributes_for :levels, :days Habit模型的accepts_nested_attributes_for :days ,以及accepts_nested_attributes_for :days User这是一个包含我所有代码的git。 让我知道。