ぼざクリタグ広場 https://hub.nizika.monster
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

58 lines
1.6 KiB

  1. class VersionRecorder
  2. EVENT_TYPES = ['create', 'update', 'discard', 'restore'].freeze
  3. def initialize record:, event_type:, created_by_user:
  4. @record = record
  5. @event_type = event_type.to_s
  6. @created_by_user = created_by_user
  7. validate_event_type!
  8. end
  9. def record!
  10. @record.with_lock do
  11. latest = latest_version
  12. if !(latest) && @event_type != 'create'
  13. raise "#{ version_class.name } first event must be create"
  14. end
  15. if @event_type == 'create' && latest
  16. raise "#{ version_class.name } create event already exists"
  17. end
  18. attrs = snapshot_attributes
  19. return latest if @event_type == 'update' && latest && same_snapshot?(latest, attrs)
  20. version_class.create!(base_attributes(latest).merge(record_key => @record).merge(attrs))
  21. end
  22. end
  23. private
  24. def latest_version = versions.order(version_no: :desc).first
  25. def versions = @record.public_send(version_association)
  26. def base_attributes latest
  27. { version_no: (latest&.version_no || 0) + 1,
  28. event_type: @event_type,
  29. created_at: Time.current,
  30. created_by_user: @created_by_user }
  31. end
  32. def same_snapshot?(version, attrs) = attrs.all? { |k, v| version.public_send(k) == v }
  33. def validate_event_type!
  34. return if EVENT_TYPES.include?(@event_type)
  35. raise ArgumentError, "Invalid event_type: #{ @event_type }"
  36. end
  37. def version_class = raise NotImplementedError
  38. def version_association = raise NotImplementedError
  39. def record_key = raise NotImplementedError
  40. def snapshot_attributes = raise NotImplementedError
  41. end