assign.rb 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  1. # Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
  2. class Sequencer::Unit::Import::Common::Model::Associations::Assign < Sequencer::Unit::Base
  3. include ::Sequencer::Unit::Import::Common::Model::Mixin::HandleFailure
  4. uses :instance, :associations, :action, :dry_run
  5. provides :action
  6. def process
  7. return if dry_run
  8. return if instance.blank?
  9. return if associations.blank? && log_associations_error
  10. register_changes
  11. instance.assign_attributes(associations)
  12. rescue => e
  13. handle_failure(e)
  14. end
  15. private
  16. # always returns true
  17. def log_associations_error
  18. return true if %i[skipped failed deactivated].include?(action)
  19. logger.error { 'associations cannot be nil' } if associations.nil?
  20. true
  21. end
  22. def register_changes
  23. return if !(action == :unchanged && changes.any?)
  24. logger.debug { "Changed instance associations: #{changes.inspect}" }
  25. state.provide(:action, :updated)
  26. end
  27. # Why not just use instance.changes?
  28. # Because it doesn't include associations
  29. # stored on OTHER TABLES (has-one, has-many, HABTM)
  30. def changes
  31. @changes ||= unfiltered_changes.reject { |_attribute, values| no_diff?(values) }
  32. end
  33. def unfiltered_changes
  34. attrs = associations.keys
  35. before = attrs.map { |attribute| instance.send(attribute) }
  36. after = associations.values
  37. attrs.zip(before.zip(after)).to_h.with_indifferent_access
  38. end
  39. def no_diff?(values)
  40. values.map!(&:sort) if values.all? { |val| val.respond_to?(:sort) }
  41. values.map!(&:presence) # [nil, []] -> [nil, nil]
  42. values.uniq.length == 1
  43. end
  44. end