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.
- #validation_record_context(dummy, record) ⇒ Object
Instance Method Details
#target_attribute(default = nil) ⇒ Object
87 88 89 |
# File 'app/validators/passthru_validator.rb', line 87 def target_attribute(default = nil) [:attribute] || default end |
#target_class ⇒ Object
83 84 85 |
# File 'app/validators/passthru_validator.rb', line 83 def target_class [:to] end |
#target_instance(record) ⇒ Object
91 92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'app/validators/passthru_validator.rb', line 91 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
79 80 81 |
# File 'app/validators/passthru_validator.rb', line 79 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 67 |
# 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 validation_record_context(dummy, record) dummy end |
#validation_record_context(dummy, record) ⇒ Object
69 70 71 72 73 74 75 76 77 |
# File 'app/validators/passthru_validator.rb', line 69 def validation_record_context(dummy, record) if dummy.is_a?(Decidim::Form) dummy.with_context( current_organization: record.try(:current_organization) || record.try(:organization), current_participatory_space: record.try(:current_participatory_space) || record.try(:participatory_space), current_component: record.try(:current_component) || record.try(:component) ) end end |