Почему события state_machine не запускаются при обратном вызове модели?

Ниже приведен код моей модели, драгоценный камень, используемый для функциональности state_machine, называется «state_machines-activerecord»:

class Response < ApplicationRecord
  state_machine initial: :created do

    after_transition on: :fire_answered, do: [:run_metrics]

    after_transition on: :fire_review, do: [:check_review]

    event :fire_sent do
      transition from: [:created, :sent], to: :sent
    end
    event :fire_review do
      transition from: [:sent, :answered], to: :review
    end
    event :fire_answered do
      transition from: [:sent, :review, :answered], to: :answered
    end
  end

  before_save :set_appropriate_events

  def set_appropriate_events
    self.state_event = 'fire_sent' if sent_time.present? && response_time.blank?
    self.state_event = 'fire_answered' if sent_time.present? && response_time.present?
    self.state_event = 'fire_review' if needs_review?
  end
end  

Значение запуска обратного вызова «self.state_event» также устанавливается на основе условий, но событие не запускается и состояние не обновляется.


person codemilan    schedule 26.11.2019    source источник


Ответы (2)


Чтобы запустить событие, вы должны использовать экземпляр модели для вызова метода. Пример: model_instance.event_name

поэтому в вашем случае вам, возможно, придется использовать следующее

def set_appropriate_events
    self.fire_sent if sent_time.present? && response_time.blank?
    self.fire_answered if sent_time.present? && response_time.present?
    self.fire_review if needs_review?
end

просто вызовите событие, и оно должно работать

person Lisbeth    schedule 26.11.2019
comment
Кстати: я не буду использовать массив, если есть только одна вещь, которую нужно сделать в [после|до] перехода after_transition on: :fire_answered, do: :run_metrics - person Lisbeth; 26.11.2019
comment
Я получаю слишком глубокий уровень стека для решения, предоставленного вами. - person codemilan; 26.11.2019
comment
хм, я не уверен, может ли он написать transition from: [:created, :sent], to: :sent, что from и to это одно и то же событие...... - person Lisbeth; 27.11.2019
comment
Да, машина может переходить в одно и то же состояние. - person codemilan; 27.11.2019

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

def set_appropriate_events
  self.state = "sent" if sent_time.present? && response_time.blank?
  self.state = "review" if sent_time.present? && response_time.present?
  self.state = "answer" if needs_review?
end

Примечание. Приведенный выше код не вызовет gem's callbacks (например, after_transition)

Если вы хотите выполнить конкретную задачу, а также обновить состояние после сохранения, НЕ используйте переходы конечного автомата, вызывайте машинные методы внутри вашего метода обратного вызова.

def set_appropriate_events
  if sent_time.present? && response_time.present?
    self.state = "review"
    run_metrics
  end
  ...
end
person Thang    schedule 26.11.2019