state_machine.rb 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. module CanBePublished
  2. class StateMachine
  3. include AASM
  4. delegate :current_state, to: :aasm
  5. def initialize(record)
  6. @record = record
  7. aasm.current_state = calculated_state
  8. end
  9. def calculated_state
  10. matching_time = Time.zone.now
  11. state = %i[archived published internal].find { |state_name| calculated_state_valid?(state_name, matching_time) }
  12. state || :draft
  13. end
  14. def calculated_state_valid?(state_name, time)
  15. date = @record.send "#{state_name}_at"
  16. date.present? && date < time
  17. end
  18. def set_timestamp
  19. override_unarchived_state if aasm.to_state == :unarchived
  20. @record.send "#{aasm.to_state}_at=", Time.zone.now.change(sec: 0)
  21. end
  22. def override_unarchived_state
  23. aasm.to_state = @record.published_at.present? ? :published : :internal
  24. end
  25. def update_using_current_user(user)
  26. %i[archived internal published].each { |state_name| update_state_using_current_user(user, state_name) }
  27. end
  28. def update_state_using_current_user(user, state_name)
  29. return if !@record.send("#{state_name}_at_changed?")
  30. new_value = @record.send("#{state_name}_at").present? ? user : nil
  31. @record.send("#{state_name}_by=", new_value)
  32. end
  33. def clear_archived
  34. @record.archived_at = nil
  35. end
  36. def save_record
  37. @record.save!
  38. end
  39. aasm do
  40. state :draft, initial: true
  41. state :internal
  42. state :published
  43. state :archived
  44. state :unarchived #magic
  45. event :internal do
  46. transitions from: :draft,
  47. to: :internal,
  48. guard: :guard_internal?,
  49. after: :set_timestamp
  50. end
  51. event :publish do
  52. transitions from: %i[draft internal],
  53. to: :published,
  54. guard: :guard_publish?,
  55. after: :set_timestamp
  56. end
  57. event :archive do
  58. transitions from: %i[published internal],
  59. to: :archived,
  60. guard: :guard_archive?,
  61. after: :set_timestamp
  62. end
  63. event :unarchive do
  64. transitions from: :archived,
  65. to: :unarchived,
  66. guard: :guard_unarchive?,
  67. after: %i[clear_archived set_timestamp]
  68. end
  69. after_all_events %i[update_using_current_user save_record mark_as_idle]
  70. error_on_all_events :mark_as_idle
  71. end
  72. def mark_as_idle
  73. aasm.send(:current_event=, nil) # nullify current_event after transitioning
  74. end
  75. def guard_internal?
  76. draft?
  77. end
  78. def guard_publish?
  79. draft? || internal?
  80. end
  81. def guard_archive?
  82. internal? || published?
  83. end
  84. def guard_unarchive?
  85. archived?
  86. end
  87. end
  88. end