如何让level.missed_days = habit.missed_days? [包括要点]
How to make level.missed_days = habit.missed_days? [Gist Included]
我正在尝试将养成良好习惯游戏化。
当用户养成新习惯时,有 5 个级别才能达到 "mastery"!每个级别都有一定的天数与之相关(如 habits.rb n_days
所示)。
这就是我卡住的地方:尽管在 :habit
_form 中选中 :level
1 的 missed_days
框,控制台显示 missed_days: 0
[=23] =] 但 missed_days: 1
为 Level.find(1)
。
错过一天是一件坏事,因为这个想法是,如果你错过了一天(通过选中一个框来表示),那么一天就会添加回你的 current_level(通过 days_missed 控制器),换句话说,只有完成的天数才计入完成一个级别。
我们怎样才能使 :level
中有多少 :missed_days
也将是 :habit
中的相同整数?
习惯 has_many
级别。
习惯_形式
<label id="<%= @habit.id %>" class="habit-id"> Missed: </label>
<% @habit.levels.each_with_index do |level, index| %>
<p>
<label id="<%= level.id %>" class="level-id"> Level <%= index + 1 %>: </label>
<%= check_box_tag nil, true, level.missed_days > 0, {class: "habit-check"} %>
<%= check_box_tag nil, true, level.missed_days > 1, {class: "habit-check"} %>
<%= check_box_tag nil, true, level.missed_days > 2, {class: "habit-check"} %>
</p>
<% end %>
<% end %>
habit-check
是关于 habit.js
$(document).ready(function()
{
$(".habit-check").change(function()
{
habit = $(this).parent().siblings(".habit-id").first().attr("id");
level = $(this).siblings(".level-id").first().attr("id");
if($(this).is(":checked"))
{
$.ajax(
{
url: "/habits/" + habit + "/levels/" + level + "/days_missed",
method: "POST"
});
}
else
{
$.ajax(
{
url: "/habits/" + habit + "/levels/" + level + "/days_missed/1",
method: "DELETE"
});
}
});
});
当我点击一个复选框时,终端会发生以下情况:
Started POST "/habits/2/levels/6/days_missed" for 127.0.0.1 at 2015-04-28 13:57:20 -0400
Processing by DaysMissedController#create as */*
Parameters: {"habit_id"=>"2", "level_id"=>"6"}
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 1]]
Habit Load (0.2ms) SELECT "habits".* FROM "habits" WHERE "habits"."user_id" = ? [["user_id", 1]]
Habit Load (0.4ms) SELECT "habits".* FROM "habits"
ActsAsTaggableOn::Tag Load (0.2ms) SELECT "tags".* FROM "tags" WHERE (LOWER(name) = LOWER('ingrain'))
Habit Load (0.2ms) SELECT "habits".* FROM "habits" WHERE "habits"."id" = ? LIMIT 1 [["id", 2]]
Level Load (0.1ms) SELECT "levels".* FROM "levels" WHERE "levels"."habit_id" = ? AND "levels"."id" = ? LIMIT 1 [["habit_id", 2], ["id", 6]]
(0.1ms) begin transaction
SQL (0.3ms) UPDATE "levels" SET "missed_days" = ?, "updated_at" = ? WHERE "levels"."id" = ? [["missed_days", 1], ["updated_at", "2015-04-28 17:57:20.960578"], ["id", 6]]
(3.0ms) commit transaction
Completed 200 OK in 27ms (ActiveRecord: 4.7ms)
habits.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
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 }
actual_days = n_days - 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
days_missed_controller.rb
class DaysMissedController < ApplicationController
before_action :logged_in_user, only: [:create, :destroy]
def create
level = Habit.find(params[:habit_id]).levels.find(params[:level_id])
level.missed_days = level.missed_days + 1
level.save!
head :ok # this returns an empty response with a 200 success status code
end
def destroy
level = Habit.find(params[:habit_id]).levels.find(params[:level_id])
level.missed_days = level.missed_days - 1
level.save!
head :ok # this returns an empty response with a 200 success status code
end
end
routes.rb
resources :habits do
resources :comments
resources :levels do
# we'll use this route to increment and decrement the missed days
resources :days_missed, only: [:create, :destroy]
end
end
要点如下:https://gist.github.com/RallyWithGalli/c66dee6dfb9ab5d338c2
您错过的天数可能没有显示,因为您的复选框实际上没有名称或 ID。他们有 "nil" 而不是......尝试:
<%= check_box_tag "missed_days_1", true, level.missed_days > 0, {class: "habit-check"} %>
或类似...第二个和第三个是 2 和 3...请记住,复选框不会给你 missed_days => 1
如果你真的想要 :missed_days =>1
然后你需要单选按钮...但你仍然需要给他们一个名字 :missed_days
"Is there a way we can make clicking a checkbox = 1 as I attempted in
the days_missed controller"
也许 - 你可以设置一个复选框的值 returns 当被选中时...... check_box_tag doco 你在第二个参数中传递它(而不是 true
)。但问题是你有多个复选框,如果你的复选框被命名为相同的东西,它们将相互覆盖,只有最后一组的值会得到 returned.
试试这样命名它们:看看你得到的结果是什么。然后处理您需要破译其含义的代码,然后将正确的值放在正确的位置。
<% @habit.levels.each_with_index do |level, index| %>
<%= check_box_tag "missed_days[#{level}][1]", true, level.missed_days > 0, {class: "habit-check"} %>
<%= check_box_tag "missed_days[#{level}][2]", true, level.missed_days > 0, {class: "habit-check"} %>
<%= check_box_tag "missed_days[#{level}][3]", true, level.missed_days > 0, {class: "habit-check"} %>
<% end %>
给定 rails' 默认值...其中第一个可能 仍 转换为 "true"...(您需要自己检查 return 值以确定是否属于这种情况)
改变模型和控制器。
habits.rb模型
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 #Added this line here.
我修好了控制器,这是我达到等级 missed_days
的地方 missed_days
:
class DaysMissedController < ApplicationController
before_action :logged_in_user, only: [:create, :destroy]
def create
habit = Habit.find(params[:habit_id])
habit.missed_days = habit.missed_days + 1
habit.save!
level = habit.levels.find(params[:level_id])
level.missed_days = level.missed_days + 1
level.save!
head :ok # this returns an empty response with a 200 success status code
end
def destroy
habit = Habit.find(params[:habit_id])
habit.missed_days = habit.missed_days - 1
habit.save
level = habit.levels.find(params[:level_id])
level.missed_days = level.missed_days - 1
level.save!
head :ok # this returns an empty response with a 200 success status code
end
end
我正在尝试将养成良好习惯游戏化。
当用户养成新习惯时,有 5 个级别才能达到 "mastery"!每个级别都有一定的天数与之相关(如 habits.rb n_days
所示)。
这就是我卡住的地方:尽管在 :habit
_form 中选中 :level
1 的 missed_days
框,控制台显示 missed_days: 0
[=23] =] 但 missed_days: 1
为 Level.find(1)
。
错过一天是一件坏事,因为这个想法是,如果你错过了一天(通过选中一个框来表示),那么一天就会添加回你的 current_level(通过 days_missed 控制器),换句话说,只有完成的天数才计入完成一个级别。
我们怎样才能使 :level
中有多少 :missed_days
也将是 :habit
中的相同整数?
习惯 has_many
级别。
习惯_形式
<label id="<%= @habit.id %>" class="habit-id"> Missed: </label>
<% @habit.levels.each_with_index do |level, index| %>
<p>
<label id="<%= level.id %>" class="level-id"> Level <%= index + 1 %>: </label>
<%= check_box_tag nil, true, level.missed_days > 0, {class: "habit-check"} %>
<%= check_box_tag nil, true, level.missed_days > 1, {class: "habit-check"} %>
<%= check_box_tag nil, true, level.missed_days > 2, {class: "habit-check"} %>
</p>
<% end %>
<% end %>
habit-check
是关于 habit.js
$(document).ready(function()
{
$(".habit-check").change(function()
{
habit = $(this).parent().siblings(".habit-id").first().attr("id");
level = $(this).siblings(".level-id").first().attr("id");
if($(this).is(":checked"))
{
$.ajax(
{
url: "/habits/" + habit + "/levels/" + level + "/days_missed",
method: "POST"
});
}
else
{
$.ajax(
{
url: "/habits/" + habit + "/levels/" + level + "/days_missed/1",
method: "DELETE"
});
}
});
});
当我点击一个复选框时,终端会发生以下情况:
Started POST "/habits/2/levels/6/days_missed" for 127.0.0.1 at 2015-04-28 13:57:20 -0400
Processing by DaysMissedController#create as */*
Parameters: {"habit_id"=>"2", "level_id"=>"6"}
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 1]]
Habit Load (0.2ms) SELECT "habits".* FROM "habits" WHERE "habits"."user_id" = ? [["user_id", 1]]
Habit Load (0.4ms) SELECT "habits".* FROM "habits"
ActsAsTaggableOn::Tag Load (0.2ms) SELECT "tags".* FROM "tags" WHERE (LOWER(name) = LOWER('ingrain'))
Habit Load (0.2ms) SELECT "habits".* FROM "habits" WHERE "habits"."id" = ? LIMIT 1 [["id", 2]]
Level Load (0.1ms) SELECT "levels".* FROM "levels" WHERE "levels"."habit_id" = ? AND "levels"."id" = ? LIMIT 1 [["habit_id", 2], ["id", 6]]
(0.1ms) begin transaction
SQL (0.3ms) UPDATE "levels" SET "missed_days" = ?, "updated_at" = ? WHERE "levels"."id" = ? [["missed_days", 1], ["updated_at", "2015-04-28 17:57:20.960578"], ["id", 6]]
(3.0ms) commit transaction
Completed 200 OK in 27ms (ActiveRecord: 4.7ms)
habits.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
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 }
actual_days = n_days - 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
days_missed_controller.rb
class DaysMissedController < ApplicationController
before_action :logged_in_user, only: [:create, :destroy]
def create
level = Habit.find(params[:habit_id]).levels.find(params[:level_id])
level.missed_days = level.missed_days + 1
level.save!
head :ok # this returns an empty response with a 200 success status code
end
def destroy
level = Habit.find(params[:habit_id]).levels.find(params[:level_id])
level.missed_days = level.missed_days - 1
level.save!
head :ok # this returns an empty response with a 200 success status code
end
end
routes.rb
resources :habits do
resources :comments
resources :levels do
# we'll use this route to increment and decrement the missed days
resources :days_missed, only: [:create, :destroy]
end
end
要点如下:https://gist.github.com/RallyWithGalli/c66dee6dfb9ab5d338c2
您错过的天数可能没有显示,因为您的复选框实际上没有名称或 ID。他们有 "nil" 而不是......尝试:
<%= check_box_tag "missed_days_1", true, level.missed_days > 0, {class: "habit-check"} %>
或类似...第二个和第三个是 2 和 3...请记住,复选框不会给你 missed_days => 1
如果你真的想要 :missed_days =>1
然后你需要单选按钮...但你仍然需要给他们一个名字 :missed_days
"Is there a way we can make clicking a checkbox = 1 as I attempted in the days_missed controller"
也许 - 你可以设置一个复选框的值 returns 当被选中时...... check_box_tag doco 你在第二个参数中传递它(而不是 true
)。但问题是你有多个复选框,如果你的复选框被命名为相同的东西,它们将相互覆盖,只有最后一组的值会得到 returned.
试试这样命名它们:看看你得到的结果是什么。然后处理您需要破译其含义的代码,然后将正确的值放在正确的位置。
<% @habit.levels.each_with_index do |level, index| %>
<%= check_box_tag "missed_days[#{level}][1]", true, level.missed_days > 0, {class: "habit-check"} %>
<%= check_box_tag "missed_days[#{level}][2]", true, level.missed_days > 0, {class: "habit-check"} %>
<%= check_box_tag "missed_days[#{level}][3]", true, level.missed_days > 0, {class: "habit-check"} %>
<% end %>
给定 rails' 默认值...其中第一个可能 仍 转换为 "true"...(您需要自己检查 return 值以确定是否属于这种情况)
改变模型和控制器。
habits.rb模型
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 #Added this line here.
我修好了控制器,这是我达到等级 missed_days
的地方 missed_days
:
class DaysMissedController < ApplicationController
before_action :logged_in_user, only: [:create, :destroy]
def create
habit = Habit.find(params[:habit_id])
habit.missed_days = habit.missed_days + 1
habit.save!
level = habit.levels.find(params[:level_id])
level.missed_days = level.missed_days + 1
level.save!
head :ok # this returns an empty response with a 200 success status code
end
def destroy
habit = Habit.find(params[:habit_id])
habit.missed_days = habit.missed_days - 1
habit.save
level = habit.levels.find(params[:level_id])
level.missed_days = level.missed_days - 1
level.save!
head :ok # this returns an empty response with a 200 success status code
end
end