Как да извършим изчисление в модел на релси?

Създадох скелета за проекти, етапи, задачи и под_задачи:

  • project има връзка "един към много" с stage
  • stage има връзка "един към много" с task
  • task има връзка "един към много" с sub_task.

Всички таблици stage, task и sub_task имат поле planned_end_date и status.

Сега искам да отпечатам общия брой етапи, задачи, под_задачи, които не са завършени до planned_end_date за всяко project в действието projects#index.

Как мога да направя това в Rails модел?

class Project < ApplicationRecord
  has_many :stages, dependent: :destroy
  validate :end_after_start

  private
  def end_after_start
    return if to_date.blank? || form_date.blank?

    if to_date < form_date
      errors.add(:to_date, "Project end date must be same or after the start date")
    end
  end
end

какво съм пробвал-

проект#index.html.erb

      <% @projects.each do |project| %>
        <tr>
          <td><%= project.project_name %></td>

          <%  @stages = Stage.where(project_id: @projects.ids) %>
          <%  @tasks = Task.where(stage_id: @stages.ids) %>
          <%  @sub_tasks = SubTask.where(task_id: @tasks.ids) %>

          <%  stage_counter = 0 %>
          <%  task_counter = 0 %>
          <%  sub_task_counter = 0 %>

          <%  @stages.each{|s| stage_counter += 1 if s.planned_end_date.past? && s.status == 0 || s.planned_end_date.past? && s.status == 2} %>
          <%  @tasks.each{|s| task_counter += 1 if s.planned_end_date.past? && s.status == 0 || s.planned_end_date.past? && s.status == 2} %>
          <%  @sub_tasks.each{|s| sub_task_counter += 1 if s.planned_end_date.past? && s.status == 0 || s.planned_end_date.past? && s.status == 2} %>

          <% @count =0 %>
          <%  @count = stage_counter + task_counter + sub_task_counter %>

          <td><span class="alert"><%= @count.to_s + " Activity Pending" %></span></td>

това, което кодът прави, е да отпечатва общия брой чакащи етапи, задачи и под_задачи за всички проекти и да отпечатва същия брой за всеки проект. Искам да отпечатам чакащи етапи+задачи+под_задачи за общия брой чакащи етапи+задачи+под_задачи на всеки проект. Какво


person rock    schedule 09.03.2020    source източник


Отговори (1)


Да, броите за ВСИЧКИ проекти, не само за текущия проект.

Това, което искаш е...

<% stages = Stage.where(project_id: project.id) %>

имайте предвид, че използваме project.id, което препраща към текущия проект във всеки цикъл, а не @projects, което е всички проекти.

По-добре може би...

<% stages = project.stages %>

И по-добре от гледна точка на производителността е да оставите базата данни да ви даде броя...

<% stage_counters = project.stages.where('planned_end_date < ?', Date.today).where(status: [0,2]).count %>

Ако ще правите сложни булеви тестове, ще ви помогне да използвате скоби, за да сте сигурни, че имате правилния ред на приоритет,

<%  @stages.each{|s| stage_counter += 1 if (s.planned_end_date.past? && s.status == 0) || (s.planned_end_date.past? && s.status == 2)} %>

Можете да направите подобно със задачи и подзадачи, като дефинирате връзката в модела...

has_many :stages, dependent: :destroy
has_many :tasks, through: :stages
has_many :sub_tasks, through: :tasks

Това ще ви позволи да направите project.tasks и project.sub_tasks

Имайте предвид, че може да искате да преместите тези изчисления в модела...

class Project

  def incomplete_stages_count
    stages.where('planned_end_date < ?', Date.today).where(status: [0,2]).count
  end

Което е по-добро и ще ви позволи да направите...

<% project.incomplete_stages_count %>

но дори тогава това означава, че моделът на проекта трябва да знае какво прави даден етап незавършен, което е главоболие, ако някога промените бизнес правилата, така че може би създайте обхват в етап

class Stage
  scope :incomplete, -> {where('planned_end_date < ?', Date.today).where(status: [0,2])}
end

И в Проект

class Project
  def incomplete_stages_count
    stages.incomplete.count
  end
end
person SteveTurczyn    schedule 09.03.2020