can_creates_and_updates.rb 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. # Copyright (C) 2012-2023 Zammad Foundation, https://zammad-foundation.org/
  2. module ApplicationModel::CanCreatesAndUpdates
  3. extend ActiveSupport::Concern
  4. # methods defined here are going to extend the class, not the instance of it
  5. class_methods do
  6. =begin
  7. create model if not exists (check exists based on id, name, login, email or locale)
  8. result = Model.create_if_not_exists(attributes)
  9. returns
  10. result = model # with all attributes
  11. =end
  12. def create_if_not_exists(data)
  13. identifier = [:id, :name, :login, :email, %i[source locale]].map { |a| data.slice(*a) }.find(&:any?) || {}
  14. case_sensitive_find_by(**identifier) || create(data)
  15. end
  16. =begin
  17. create or update model (check exists based on id, name, login, email or locale)
  18. result = Model.create_or_update(attributes)
  19. returns
  20. result = model # with all attributes
  21. =end
  22. def create_or_update(data)
  23. attr = (data.keys & %i[id name login email locale]).first
  24. raise ArgumentError, __('One of the required parameters must be provided, but none was found.') if attr.nil?
  25. record = case_sensitive_find_by(**data.slice(attr))
  26. record.nil? ? create(data) : record.tap { |r| r.update(data) }
  27. end
  28. =begin
  29. Model.create_if_not_exists with ref lookups
  30. result = Model.create_if_not_exists_with_ref(attributes)
  31. returns
  32. result = model # with all attributes
  33. =end
  34. def create_if_not_exists_with_ref(data)
  35. data = association_name_to_id_convert(data)
  36. create_or_update(data)
  37. end
  38. =begin
  39. Model.create_or_update with ref lookups
  40. result = Model.create_or_update(attributes)
  41. returns
  42. result = model # with all attributes
  43. =end
  44. def create_or_update_with_ref(data)
  45. data = association_name_to_id_convert(data)
  46. create_or_update(data)
  47. end
  48. def case_sensitive_find_by(**attrs)
  49. return nil if attrs.empty?
  50. return find_by(**attrs) if Rails.application.config.db_case_sensitive || attrs.values.none?(String)
  51. where(**attrs).find { |record| record[attrs.keys.first] == attrs.values.first }
  52. end
  53. end
  54. included do
  55. private_class_method :case_sensitive_find_by
  56. end
  57. end