How to only show previous & current level checkboxes?

时间:2015-05-04 19:49:03

标签: ruby-on-rails ruby model-view-controller checkbox

When a user is on Level 1 how can we only show Level 1 checkboxes? If a user is on Level 2 how can we only show Level 2 & Level 1 checkboxes? Etc...

Right now it shows all 5 levels regardless of current level, which can be confusing for a user:

<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 %>

enter image description here

habit.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 } - 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

habits_controller

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 = current_user.habits.order("date_started DESC")
    end
  end

  def show
  end

  def new
    @habit = current_user.habits.build
  end

  def edit
  end

  def create
    @habit = current_user.habits.build(habit_params)
    if  @habit.save_with_current_level
        track_activity @habit
        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, 
      :trigger,
      :tag_list,
      :current_level,
      :missed_days,
      :target, 
      :reward,
      :comment,
      :private,
      :order,
      :date_started,
      :missed_one, 
      :committed => [],
      levels_attributes: [
      :missed_days])
  end
end

Here's the gist of it: https://gist.github.com/RallyWithGalli/c66dee6dfb9ab5d338c2

Thank you so much for your time! And if you have some spare time here's a similar problem: How to count current level missed_days?

1 个答案:

答案 0 :(得分:1)

好的,我想我已经绕过你的代码。你的html来自show行动吗?除非另有说明,否则我会继续这个假设。所以@habit在set_habit before_action中设置。因此:

@habit.levels 

将返回一系列习惯级别。显然,当创造这种习惯时,它会创建所有五个级别?您没有显示level.rb模型,但看起来您的关系与habit.rb代码相反。所以等级属于习惯。看起来你在这里创造了所有五个:

def save_with_current_level
    self.levels.build
    self.levels.build
    self.levels.build
    self.levels.build
    self.levels.build
    self.save
 end

因此,要么仅在达到某个级别时创建一个级别,要么在视图中的循环代码中跳过该级别(如果尚未实现)。

<label id="<%= @habit.id %>" class="habit-id"> Missed: </label>
<% @habit.levels.each_with_index do |level, index| %>
  <% if @habit.current_level >= (index + 1) %>
    <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 %>