can_cleanup_param.rb 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. # Copyright (C) 2012-2023 Zammad Foundation, https://zammad-foundation.org/
  2. module ApplicationModel::CanCleanupParam
  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. remove all not used model attributes of params
  8. result = Model.param_cleanup(params)
  9. for object creation, ignore id's
  10. result = Model.param_cleanup(params, true)
  11. returns
  12. result = params # params with valid attributes of model
  13. =end
  14. def param_cleanup(params, new_object = false, inside_nested = false, exceptions = true)
  15. if params.respond_to?(:permit!)
  16. params = params.permit!.to_h
  17. end
  18. if params.nil?
  19. raise Exceptions::UnprocessableEntity, "No params for #{self}!"
  20. end
  21. # cleanup each member of array
  22. if params.is_a? Array
  23. return params.map { |elem| param_cleanup(elem, new_object, inside_nested) }
  24. end
  25. data = {}
  26. params.each do |key, value|
  27. data[key.to_s] = value
  28. end
  29. # ignore id for new objects
  30. if new_object && params[:id]
  31. data.delete('id')
  32. end
  33. # get associations by id
  34. attribute_associations = {}
  35. reflect_on_all_associations.map do |assoc|
  36. class_name = assoc.options[:class_name]
  37. next if !class_name
  38. attribute_associations["#{assoc.name}_id"] = assoc
  39. end
  40. # only use object attributes
  41. clean_params = ActiveSupport::HashWithIndifferentAccess.new
  42. new.attributes.each_key do |attribute|
  43. next if !data.key?(attribute)
  44. # check reference records, referenced by _id attributes
  45. if attribute_associations[attribute].present? && data[attribute].present? && !attribute_associations[attribute].klass.lookup(id: data[attribute])
  46. raise Exceptions::UnprocessableEntity, "Invalid value for param '#{attribute}': #{data[attribute].inspect}" if exceptions
  47. next
  48. end
  49. clean_params[attribute] = data[attribute]
  50. end
  51. clean_params['form_id'] = data['form_id'] if data.key?('form_id') && new.respond_to?(:form_id)
  52. if inside_nested
  53. clean_params['id'] = params[:id] if params[:id].present?
  54. clean_params['_destroy'] = data['_destroy'] if data['_destroy'].present?
  55. end
  56. nested_attributes_options.each_key do |nested|
  57. nested_key = "#{nested}_attributes"
  58. target_klass = reflect_on_association(nested).klass
  59. next if data[nested_key].blank?
  60. nested_data = data[nested_key]
  61. if data.key? 'form_id'
  62. case nested_data
  63. when Array
  64. nested_data.each { |item| item['form_id'] = data['form_id'] }
  65. else
  66. nested_data['form_id'] = data['form_id']
  67. end
  68. end
  69. clean_params[nested_key] = target_klass.param_cleanup(nested_data, new_object, true)
  70. end
  71. # we do want to set this via database
  72. filter_unused_params(clean_params)
  73. end
  74. private
  75. =begin
  76. remove all not used params of object (per default :updated_at, :created_at, :updated_by_id and :created_by_id)
  77. if import mode is enabled, just do not used :action and :controller
  78. result = Model.filter_unused_params(params)
  79. returns
  80. result = params # params without listed attributes
  81. =end
  82. def filter_unused_params(data)
  83. params = %i[action controller updated_at created_at updated_by_id created_by_id updated_by created_by]
  84. if Setting.get('import_mode') == true
  85. params = %i[action controller]
  86. end
  87. params.each do |key|
  88. data.delete(key)
  89. end
  90. data
  91. end
  92. end
  93. =begin
  94. merge preferences param
  95. record = Model.find(123)
  96. new_preferences = record.param_preferences_merge(param_preferences)
  97. =end
  98. def param_preferences_merge(new_params)
  99. return new_params if new_params.blank?
  100. return new_params if preferences.blank?
  101. new_params[:preferences] = preferences.merge(new_params[:preferences] || {})
  102. new_params
  103. end
  104. end