123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151 |
- # Copyright (C) 2012-2023 Zammad Foundation, https://zammad-foundation.org/
- module ApplicationModel::CanCleanupParam
- extend ActiveSupport::Concern
- # methods defined here are going to extend the class, not the instance of it
- class_methods do
- =begin
- remove all not used model attributes of params
- result = Model.param_cleanup(params)
- for object creation, ignore id's
- result = Model.param_cleanup(params, true)
- returns
- result = params # params with valid attributes of model
- =end
- def param_cleanup(params, new_object = false, inside_nested = false, exceptions = true)
- if params.respond_to?(:permit!)
- params = params.permit!.to_h
- end
- if params.nil?
- raise Exceptions::UnprocessableEntity, "No params for #{self}!"
- end
- # cleanup each member of array
- if params.is_a? Array
- return params.map { |elem| param_cleanup(elem, new_object, inside_nested) }
- end
- data = {}
- params.each do |key, value|
- data[key.to_s] = value
- end
- # ignore id for new objects
- if new_object && params[:id]
- data.delete('id')
- end
- # get associations by id
- attribute_associations = {}
- reflect_on_all_associations.map do |assoc|
- class_name = assoc.options[:class_name]
- next if !class_name
- attribute_associations["#{assoc.name}_id"] = assoc
- end
- # only use object attributes
- clean_params = ActiveSupport::HashWithIndifferentAccess.new
- new.attributes.each_key do |attribute|
- next if !data.key?(attribute)
- # check reference records, referenced by _id attributes
- if attribute_associations[attribute].present? && data[attribute].present? && !attribute_associations[attribute].klass.lookup(id: data[attribute])
- raise Exceptions::UnprocessableEntity, "Invalid value for param '#{attribute}': #{data[attribute].inspect}" if exceptions
- next
- end
- clean_params[attribute] = data[attribute]
- end
- clean_params['form_id'] = data['form_id'] if data.key?('form_id') && new.respond_to?(:form_id)
- if inside_nested
- clean_params['id'] = params[:id] if params[:id].present?
- clean_params['_destroy'] = data['_destroy'] if data['_destroy'].present?
- end
- nested_attributes_options.each_key do |nested|
- nested_key = "#{nested}_attributes"
- target_klass = reflect_on_association(nested).klass
- next if data[nested_key].blank?
- nested_data = data[nested_key]
- if data.key? 'form_id'
- case nested_data
- when Array
- nested_data.each { |item| item['form_id'] = data['form_id'] }
- else
- nested_data['form_id'] = data['form_id']
- end
- end
- clean_params[nested_key] = target_klass.param_cleanup(nested_data, new_object, true)
- end
- # we do want to set this via database
- filter_unused_params(clean_params)
- end
- private
- =begin
- remove all not used params of object (per default :updated_at, :created_at, :updated_by_id and :created_by_id)
- if import mode is enabled, just do not used :action and :controller
- result = Model.filter_unused_params(params)
- returns
- result = params # params without listed attributes
- =end
- def filter_unused_params(data)
- params = %i[action controller updated_at created_at updated_by_id created_by_id updated_by created_by]
- if Setting.get('import_mode') == true
- params = %i[action controller]
- end
- params.each do |key|
- data.delete(key)
- end
- data
- end
- end
- =begin
- merge preferences param
- record = Model.find(123)
- new_preferences = record.param_preferences_merge(param_preferences)
- =end
- def param_preferences_merge(new_params)
- return new_params if new_params.blank?
- return new_params if preferences.blank?
- new_params[:preferences] = preferences.merge(new_params[:preferences] || {})
- new_params
- end
- end
|