Как создать задачу для обновления атрибута родителя на основе даты последнего ребенка - PullRequest
1 голос
/ 13 апреля 2020

Я пытаюсь создать веб-приложение для небольшого клини c, и я застрял.

Я использую:

  • Ruby 2.6 .5
  • Rails 6.0.2
  • Драгоценный камень "всегда" для запуска задачи один раз в неделю.
  • Драгоценный камень 'simple_enum' для создания перечисления :status для Пациент.

Я пытаюсь создать задачу для установки статуса пациента на основе даты последней встречи.

Если Пациент не назначает встречи на более длительный срок чем через шесть месяцев, то статус изменится на неактивный. Я делаю это, чтобы показать список неактивных пользователей, чтобы пользователь мог связаться с ними и связаться, что-то вроде этого:

  • , если последний прием у пациента был 6 месяцев или go, установите статус неактивный.
  • , если прошло менее 6 месяцев, установите его активным.
  • Я хочу исключить поиск, если значение Pacient.appointments равно nil, поскольку я уже устанавливаю ожидающий в after_create в модели.

Я уже пробовал что-то подобное в консоли, чтобы посмотреть, получу ли я куда-нибудь:

Pacient.find_each do |pacient|
  pacient.appointments.order(:appointment_date).last
end

, и я получил последнее назначение на основе дата, но я не смог написать код для фактического изменения статуса.

Родительская модель:

#app/models/pacient.rb

class Pacient < ApplicationRecord
  has_many :appointments
  as_enum :status, [:active, :inactive, :pending], pluralize_scopes: false
  after_create :set_pacient_status

  def set_pacient_status
    pending!
  end

end

Дочерняя модель:

#app/models/appointment.rb

class Appointment < ApplicationRecord
  belongs_to :pacient
  validates_presence_of %w[appointment_date pacient]
end

Расписание Everyever:

#config/schedule.rb

every 1.week do
  rake 'pacients:set_status'
end

Грабли:

#lib/tasks/pacients.rake

namespace :pacients do
  desc 'set pacient status based on appointment_date'
  task set_status: :environment do
    #code here
  end
end

Ответы [ 2 ]

1 голос
/ 13 апреля 2020

Вам не нужен камень simple_enum. ActiveRecord::Enum был встроен во фреймворк как минимум с Rails 4. Используйте его вместо добавления лишней зависимости.

class Pacient < ApplicationRecord
  # This is built into rails
  enum status: {
    active: 0, 
    inactive: 1, 
    pending: 2
  }
  has_many :appointments
  after_create :set_pacient_status

  def set_pacient_status
    pending!
  end
end

Чтобы обновить всех пользователей, у которых была встреча в последние шесть месяцев, вы бы do:

# update all users with an appointment in the last 6 months
Pacient.joins(:appointments)
       .group('pacients.id')
       .where(
         appointments: { appointment_date: Float::INFINITY..6.months.ago }
       )
       .update_all(status: :active)

Это делает один запрос на обновление и будет работать намного лучше, чем извлечение всех записей из БД и выполнение N запросов на обновление.

Обратный запрос может быть записан как:

# update all users without an appointment in the last 6 months
Pacient.left_joins(:appointments)
       .group('pacients.id')
       .where(
         appointments: { appointment_date: Float::INFINITY..6.months.ago },
         id: nil
       )
       .update_all(status: :inactive)
0 голосов
/ 13 апреля 2020

Проверьте, назначена ли встреча exists? в течение шести месяцев, затем обновите статус пациента:

Pacient.find_each do |pacient|
  pacient.update_column(:status,pacient.appointments.where('appointment_date > ?',6.months.ago).exists? ? 'active' : 'inactive')
end
...