Class: PassthruValidator
- Inherits:
-
ActiveModel::EachValidator
- Object
- ActiveModel::EachValidator
- PassthruValidator
- Defined in:
- app/validators/passthru_validator.rb
Overview
This validator passes through the file upload validations on a record attribute to an associated record. Useful e.g. with the forms that are not aware of the actual record’s validators but they still need to apply the same validators as in the model they represent. Needs to be configured with the target class and optionally the target attribute where the validators are fetched from. By default the attribute name matches the attribute the validator is set for. Works only for each validators.
Example:
class ParticipantForm < Decidim::Form
# Passes both the validator class only
validates :avatar_image, passthru: { to: Person }
# Passes both the validator class and attribute
validates :image, passthru: { to: Person, attribute: :avatar_image }
end
Instance Method Summary collapse
- #target_attribute(default = nil) ⇒ Object
- #target_class ⇒ Object
- #target_instance(record) ⇒ Object
- #target_validators(attribute) ⇒ Object
-
#validate_each(record, attribute, value) ⇒ Object
record - Form object (e.g. Decidim::UploadValidationForm) attribute - The attribute to validate (e.g. :avatar) value - Blob’s signed id (e.g. “eyJfcmFpbHMi…”).
-
#validation_record(record) ⇒ Object
Creates a dummy validation record that passes the correct file upload validation context from the original record for the validators.
Instance Method Details
#target_attribute(default = nil) ⇒ Object
76 77 78 |
# File 'app/validators/passthru_validator.rb', line 76 def target_attribute(default = nil) [:attribute] || default end |
#target_class ⇒ Object
72 73 74 |
# File 'app/validators/passthru_validator.rb', line 72 def target_class [:to] end |
#target_instance(record) ⇒ Object
80 81 82 83 84 85 86 87 88 89 90 91 92 |
# File 'app/validators/passthru_validator.rb', line 80 def target_instance(record) instance_attributes = if [:with].respond_to?(:call) [:with].call(record) else [:with] || {} end instance_attributes.each do |key, val| instance_attributes[key] = val.call(record) if val.respond_to?(:call) end target_class.new(instance_attributes) end |
#target_validators(attribute) ⇒ Object
68 69 70 |
# File 'app/validators/passthru_validator.rb', line 68 def target_validators(attribute) target_class.validators_on(target_attribute(attribute)) end |
#validate_each(record, attribute, value) ⇒ Object
record - Form object (e.g. Decidim::UploadValidationForm) attribute - The attribute to validate (e.g. :avatar) value - Blob’s signed id (e.g. “eyJfcmFpbHMi…”)
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
# File 'app/validators/passthru_validator.rb', line 24 def validate_each(record, attribute, value) return unless target_class dummy_attr = target_attribute(attribute) # Create a dummy record for which the validations are actually run on dummy = validation_record(record) if dummy.respond_to?(dummy_attr) && !(value.class <= ActiveStorage::Attached) dummy.public_send("#{dummy_attr}=", value) value = dummy.public_send(dummy_attr) elsif dummy.respond_to? :file dummy.public_send("file=", value) value = dummy.public_send(:file) end target_validators(attribute).each do |validator| next unless validator.is_a?(ActiveModel::EachValidator) next unless check_validator_conditions(dummy, validator) dummy.errors.clear validator.validate_each(dummy, dummy_attr, value) dummy.errors[dummy_attr].each do |err| record.errors.add(attribute, err) end end end |
#validation_record(record) ⇒ Object
Creates a dummy validation record that passes the correct file upload validation context from the original record for the validators.
54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'app/validators/passthru_validator.rb', line 54 def validation_record(record) dummy = target_instance(record) if dummy.is_a?(Decidim::Attachment) if record.respond_to?(:attached_to) dummy.attached_to = record.attached_to elsif record.respond_to?(:organization) dummy.attached_to = record.organization end elsif dummy.respond_to?(:organization=) && record.respond_to?(:organization) dummy.organization = record.organization end dummy end |