Конечный автомат AASM - как работают обратные вызовы? - PullRequest
0 голосов
/ 18 апреля 2020

Я мог бы быть действительно плотным, но мне трудно понять обратные вызовы, так как документы говорят это так:

begin
  event           before_all_events
  event           before
  event           guards
  transition      guards
  old_state       before_exit
  old_state       exit
                  after_all_transitions
  transition      after # 1st appearance
  new_state       before_enter
  new_state       enter
  ...update state...
  event           before_success      # if persist successful
  transition      success             # if persist successful
  event           success             # if persist successful
  old_state       after_exit
  new_state       after_enter
  event           after # 2nd appearance
  event           after_all_events
rescue
  event           error
  event           error_on_all_events
ensure
  event           ensure
  event           ensure_on_all_events
end

Моя путаница в том, что, похоже, много избыточности. Например, after встречается дважды, как отмечено выше. То же самое делают guards и success.

У меня также есть конкретный c вариант использования, мой код выглядит так:

event :to_complete, after: :set_overall_status do
  transitions from: [:pending_work, :in_progress], to: :complete
end

def set_overall_status
  if self.aasm_state == "complete" && self.paid == true
    self.update_column(:status, 1)
  end
end

Когда я звоню to_complete! I Хотелось бы установить новый атрибут status одновременно (так как удар сохраняет запись). То есть я хотел бы написать:

def set_overall_status
  if self.aasm_state == "complete" && self.paid == true
    self.status = 1
  end
end

Однако я не могу понять, как это сделать. Мой текущий код с обратным вызовом after и update_column работает. Если я изменю update_column на простое присвоение атрибута, произойдет сбой.

Это означает, что обратный вызов after срабатывает после того, как взрыв уже обновил запись. Подразумевается, что этот after является вторым экземпляром в списке обратных вызовов, которые я скопировал из документов.

Поэтому я решил, что мне потребуется использовать обратный вызов, когда new_state вступит в силу, но до завершения обновления взрыва. Я попробовал before_enter и enter, но они не сработали. Например:

event :to_complete, enter: :set_overall_status do
  transitions from: [:pending_work, :in_progress], to: :complete
end

def set_overall_status
  if self.aasm_state == "complete" && self.paid == true
    self.status = 1
  end
end
...