如何整合:错过的日子:养成习惯的日子.rb?
我们如何整合t.integer :missed
了t.text :committed
这样做
-
当用户检查他时
:missed
3:committed
日期在:level
他必须重新启动:level
? -
对于每一个
: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似乎在正确的轨道上,但你现在需要将一些逻辑添加到关卡模型中。 如果您想了解详细信息,请与我聊天。
我认为程序设计必须稍加重新评估。 我认为levels
和days
应该是单独的模型,其中包含level
和missed
列(遵循SRP的概念,如他在评论中提到的@dgilperez)。 因此,我们最终得到四个模型: User
, Habit
, Level
和Day
,具有以下关联:
- 用户 :
has_many :habits
:has_many :habits
,has_many :levels
- 习惯 :
belongs_to:user
,has_many :levels
和has_many :days, through: :levels #for being able to access Habit.find(*).days
- 级别 :
belongs_to :user
,belongs_to :habit
和has_many :days
- Day :
belongs_to :level
,belongs_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_days
和missed_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。 让我知道。