如何列出标签 :committed for Today?

How to List Tags :committed for Today?

<% tag_cloud Habit.tag_counts, %w{m} do |tag, css_class| %>
 <%= link_to tag.name, taghabits_path(tag.name), class: css_class %>
<% end %>

以上代码列出了所有习惯标签。但是我们怎样才能让它只列出今天有习惯:committed的标签呢?

在习惯 _form <%= f.collection_check_boxes :committed, Date::DAYNAMES, :downcase, :to_s %> 中,用户可以选择在哪几天 :committed 养成自己的习惯。

[ ] Sunday [ ] Monday [ ] Tuesday [ ] Wednesday [ ] Thursday [ ] Friday [ ] Saturday

习惯模型

class Habit < ActiveRecord::Base
    belongs_to :user
    before_save :set_level
    acts_as_taggable
    serialize :committed, Array

    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

protected
    def set_level
     self.level = levels
    end 
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

因为这段代码是在侧边栏中呈现的,我认为我们必须向 ApplicationController 添加控制器逻辑,就像我对 set_top_3_goals 所做的那样。

应用程序控制器

class ApplicationController < ActionController::Base
  before_action :set_top_3_goals
  protect_from_forgery with: :exception
  include SessionsHelper

  def set_top_3_goals
    @top_3_goals = current_user.goals.unaccomplished.top_3 if logged_in?
  end

  private

    # Confirms a logged-in user.
    def logged_in_user
      unless logged_in?
        store_location
        flash[:danger] = "Please log in."
        redirect_to login_url
      end
    end
end

views/layouts/_sidebar.html.erb

<div id="sidebarsectiontop" class="panel panel-default">
<div id="sidebarheadingtop" class="panel-heading"><h5><b>Today</b></h5></div>
  <%= render 'habits/today' %>
</div>
<div id="sidebarsection" class="panel panel-default">
<div id="sidebarheading" class="panel-heading"><h5><b>Upcoming</b></h5></div>
  <%= render 'goals/upcoming' %>
</div>

非常感谢您的宝贵时间=]

由于您将 :committed 属性定义为 serialize,您无法直接查询数据库以获取特定日期(今天)内的习惯,因此您需要将所有习惯来自数据库,然后像这样用所需的承诺日期过滤它们:

class Habit < ActiveRecord::Base
  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
end

然后在您的 ApplicationController 中,因为您希望侧边栏跨站点显示:

class ApplicationController < ActionController::Base
  before_action :load_todays_habits

  private 

  def load_todays_habits
    @user_tags = current_user.habits.comitted_for_today.tag_counts
    @all_tags  = Habit.comitted_for_today.tag_counts
  end
end

最后,您的视图可以使用用户标签的第一个列表或所有标签的最后一个列表,两者都是今天提交的:

<% tag_cloud @user_tags, %w{m} do |tag, css_class| %>
  <%= link_to tag.name, taghabits_path(tag.name), class: css_class %>
<% end %>

<% tag_cloud @all_tags, %w{m} do |tag, css_class| %>
  <%= link_to tag.name, taghabits_path(tag.name), class: css_class %>
<% end %>

Extra ball:如果您使用 PostgreSQL 的本机数组支持,您可以改进代码并将 class 方法变成具有特定习惯承诺日的范围( see here for a good guide)。