如何修复level.rb来处理:承诺的日子? [英] How to fix level.rb to work with :committed days?
问题描述
最初我有:承诺
工作精美的日子,但是为了适应用户检查他是否错过了一个:committed
day我现在收到与有关的代码的错误信息:commit
:
Originally I had :committed
days working beautifully, but upon changing up the models a bit in order to accommodate the User's ability to check off if he missed a :committed
day I now get an error message for the code relating to :committed
:
未定义的方法to_date为nil:NilClass
行#30 n_days =((date_started.to_date)..日期。今天).count {| date | committed_wdays.include? date.wday}
这段代码来自习惯模型:
This code comes from the habit model:
class Habit < ActiveRecord::Base
belongs_to :user
has_many :levels
has_many :days, through: :levels #for being able to access Habit.find(*).days
accepts_nested_attributes_for :levels, :days
before_save :set_level
acts_as_taggable
serialize :committed, Array
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
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 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
这背后的逻辑是,用户创建一个习惯他想挑战要实现掌握习惯,他必须完成5级。每个级别都有一定数量的:承诺
天,必须在推进之前完成,如上所述,用 n_days
分解。
The logic behind it all is that a User creates a habit he wants to challenge. To achieve "mastery" in the habit he must complete 5 levels. Each level has a certain amount of :committed
days that must be completed before advancing, as broken down above with n_days
.
用户在_form中提交他希望做的习惯的日子(星期六)。例如他可以选择太阳,wed,sat。那么应用程序应该根据非 :commit $计算
n_days
c $ c> days(一天中的10次通过它移到第二级)。
The User commits in the _form to what days (Sun thru Sat) he wants to do the habit. For example he could just choose sun, wed, sat. Then the app should only calculate n_days
according to non-:missed
:committed
days (once 10 of those days passes it moves onto the 2nd level).
class Level < ActiveRecord::Base
belongs_to :habit
belongs_to :user
has_many :days
accepts_nested_attributes_for :days
def evaluate
if days.where(missed: true ).count == days_needed
update_attributes(passed: false)
else
update_attributes(passed: true)
end
end
end
class Day < ActiveRecord::Base
belongs_to :level
belongs_to :habit
end
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
def show
end
def new
@goal = current_user.goals.build
@habit = current_user.habits.build
@level = current_user.levels.build
3.times { @level.days.build }
end
def edit
end
def create
@habit = current_user.habits.build(habit_params)
@levels = @habit.levels
if @habit.evaluate(@user)
redirect_to @habit, notice: 'Habit was successfully created.'
else
@feed_items = []
render 'pages/home'
end
end
def update
if @habit.update(habit_params)
redirect_to @habit, notice: 'Habit was successfully updated.'
else
render action: 'edit'
end
end
def destroy
@habit.destroy
redirect_to habits_url
end
private
def set_habit
@habit = Habit.find(params[:id])
end
def correct_user
@habit = current_user.habits.find_by(id: params[:id])
redirect_to habits_path, notice: "Not authorized to edit this habit" if @habit.nil?
end
def habit_params
params.require(:habit).permit(
:user_id,
:level,
:left,
:date_started,
:trigger,
:target,
:positive,
:negative,
:tag_list,
:committed => [],
:levels_attributes => [
:passed,
:days_attributes => [
:missed,:level_id]])
end
end
<%= simple_form_for(@habit) do |f| %>
<%= f.error_notification %>
<div class="america">
<form>
<div class="committed">
<%= f.label "Committed to:" %>
<%= f.collection_check_boxes :committed, Date::DAYNAMES, :downcase, :to_s %>
</div>
<p>
<div class="date-group">
<label> Started: </label>
<%= f.date_select :date_started, :order => [:month, :day, :year], class: 'date-select' %>
</div>
</p>
<p>
<%= f.text_field :trigger, class: 'form-control', placeholder: 'Enter Trigger' %></p>
<p>
<%= f.text_field :tag_list, habit: @habit.tag_list.to_s.titleize, class: 'form-control', placeholder: 'Enter Action' %>
</p>
<p>
<%= f.text_field :target, class: 'form-control', placeholder: 'Enter Target' %>
</p>
<p>
<%= f.text_field :positive, class: 'form-control', placeholder: 'Enter Reward' %>
</p>
<% 5.times.each_with_index do |number, index| %>
<h1>Level <%= index + 1 %></h1>
<%= f.fields_for :levels do |level| %>
<%= level.fields_for :days do |day| %>
<%= day.label :missed %>
<%= day.check_box :missed %> <br/>
<% end %>
<% end %>
<% end %>
<div class="america2">
<%= button_tag(type: 'submit', class: "btn") do %>
<span class="glyphicon glyphicon-plus"></span>
<% end %>
<%= link_to habits_path, class: 'btn' do %>
<span class="glyphicon glyphicon-chevron-left"></span>
<% end %>
<%= link_to @habit, method: :delete, data: { confirm: 'Are you sure?' }, class: 'btn' do %>
<span class="glyphicon glyphicon-trash"></span>
<% end %>
</div>
</form>
</div>
<% end %>
<!-- Default bootstrap panel contents -->
<div id="valuations" class="panel panel-default">
<div class="panel-heading"><h4><b>HABITS</b></h4></div>
<!-- Table -->
<table>
<thead>
<tr>
<th>Level</th>
<th>Left</th>
<th>Strike</th>
<th>Trigger</th>
<th>Action</th>
<th>Target</th>
<th>Reward</th>
<th>Days</th>
</tr>
</thead>
<tbody>
<% @habits.each do |challenged| %>
<tr>
<td><%= challenged.level %></td>
<td><%= challenged.left %></td>
<td>
<%= link_to edit_habit_path(challenged) do %>
<%= [params[:missed]].flatten.length %>
<% end %></td>
<td><%= challenged.trigger %></td>
<td class="category">
<b><%= raw challenged.tag_list.map { |t| link_to t.titleize, taghabits_path(t) }.join(', ') %></b>
</td>
<td><%= challenged.target %></td>
<td><%= challenged.positive %></td>
<td class= "committed">
<%= challenged.committed.map { |d| d.titleize[0,3] }.join ', ' %></td>
</tr>
<% end %>
</tbody>
</table>
</div>
非常感谢您的帮助!
这些代码中的一些代码来自此答案:如何整合:错过的日期与:级别?,这搞砸了与这个答案有效:如何制作:基于:承诺日的级别更改
Some of this code came from this answer here: How to integrate :missed days with :level? which messed up what worked with this answer: How to Make :level Change Based on :committed Days?
推荐答案
似乎 date_started
是您的 Habit
model,可能是一个数据库列,在 date_started
中有NULL。打开你的Rails控制台,看看是否这样:
It appears that date_started
is an attribute of your Habit
model, probably a database column, and that there are NULLs in date_started
. Open up your Rails console and see if this is the case with:
Habit.where(date_started: nil).count
如果您希望 date_started
不应该为空,添加一个验证来确保是这样。一旦你测试了将该空格保存到该列中的代码,那么验证错误就会指出你的错误。
If you expect that date_started
should never be null, add a validation to ensure that is the case. As soon as you test the code which is saving nulls into that column, the validation errors will point you to the bug.
另一方面,如果你想允许 date_started
中的null,然后重写您的级别
方法以允许。
On the other hand, if you want to allow nulls in date_started
, then rewrite your levels
method to allow for that.
这篇关于如何修复level.rb来处理:承诺的日子?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!