Class: Decidim::AttributeObject::Form
- Inherits:
-
Object
- Object
- Decidim::AttributeObject::Form
- Includes:
- ActiveModel::Validations, Model
- Defined in:
- lib/decidim/attribute_object/form.rb
Overview
This is the main Form class that provides the functionality for all core forms that take in user input from the user interface forms and converts the inputs to expected formats.
This replaces the Rectify::Form classes in Decidim which used to provide similar functionality. The API provided by this class is largely compatible with ‘Rectify::Form`.
Direct Known Subclasses
Constant Summary
Constants included from TypeMap
TypeMap::Boolean, TypeMap::Decimal
Instance Attribute Summary collapse
-
#context ⇒ Object
readonly
Returns the value of attribute context.
Class Method Summary collapse
- .ensure_hash(object) ⇒ Object
- .from_model(model) ⇒ Object
- .from_params(params, additional_params = {}) ⇒ Object
- .hash_from(params) ⇒ Object
- .infer_model_name ⇒ Object
- .mimic(model_name) ⇒ Object
- .mimicked_model_name ⇒ Object
-
.model_name ⇒ Object
Converts the mimicked name to ActiveModel naming.
Instance Method Summary collapse
-
#map_model(_model) ⇒ Object
Use the map_model method within the form implementations to map any custom form-specific attributes from the model to the form.
- #persisted? ⇒ Boolean
- #to_key ⇒ Object
-
#to_model ⇒ Object
Required for the active model naming to work correctly to form the HTML class attributes for the form elements (e.g. edit_account instead of edit_account_form).
- #to_param ⇒ Object
-
#valid?(_context = nil) ⇒ Boolean
Although we are running the nested attributes validations through the NestedValidator, we still need to check for the errors in the nested attributes after the main validations are run in case the main validations are adding errors to some of the nested attributes.
- #with_context(new_context) ⇒ Object
Methods included from Model
#[], #[]=, #attributes, #attributes_with_values, #initialize, #to_h
Instance Attribute Details
#context ⇒ Object (readonly)
Returns the value of attribute context.
16 17 18 |
# File 'lib/decidim/attribute_object/form.rb', line 16 def context @context end |
Class Method Details
.ensure_hash(object) ⇒ Object
76 77 78 79 80 81 82 |
# File 'lib/decidim/attribute_object/form.rb', line 76 def self.ensure_hash(object) if object.is_a?(Hash) object else {} end end |
.from_model(model) ⇒ Object
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
# File 'lib/decidim/attribute_object/form.rb', line 40 def self.from_model(model) form_attributes = attribute_types.keys.each_with_object({}) do |key, attrs| next unless model.respond_to?(key) value = model.send(key) attrs[key] = case value when ActiveStorage::Attached::One value..try(:blob) when ActiveStorage::Attached::Many value..map(&:blob) else value end end form = new(form_attributes) form.map_model(model) form end |
.from_params(params, additional_params = {}) ⇒ Object
62 63 64 65 66 67 68 69 |
# File 'lib/decidim/attribute_object/form.rb', line 62 def self.from_params(params, additional_params = {}) params_hash = hash_from(params) mimicked_params = ensure_hash(params_hash[mimicked_model_name]) attributes_hash = params_hash.merge(mimicked_params).merge(additional_params) new(attributes_hash) end |
.hash_from(params) ⇒ Object
71 72 73 74 |
# File 'lib/decidim/attribute_object/form.rb', line 71 def self.hash_from(params) params = params.to_unsafe_h if params.respond_to?(:to_unsafe_h) params.with_indifferent_access end |
.infer_model_name ⇒ Object
26 27 28 29 30 31 32 33 |
# File 'lib/decidim/attribute_object/form.rb', line 26 def self.infer_model_name return :form unless name class_name = name.split("::").last return :form if class_name == "Form" class_name.chomp("Form").underscore.to_sym end |
.mimic(model_name) ⇒ Object
18 19 20 |
# File 'lib/decidim/attribute_object/form.rb', line 18 def self.mimic(model_name) @model_name = model_name.to_s.underscore.to_sym end |
.mimicked_model_name ⇒ Object
22 23 24 |
# File 'lib/decidim/attribute_object/form.rb', line 22 def self.mimicked_model_name @model_name || infer_model_name end |
.model_name ⇒ Object
Converts the mimicked name to ActiveModel naming.
36 37 38 |
# File 'lib/decidim/attribute_object/form.rb', line 36 def self.model_name ActiveModel::Name.new(self, nil, mimicked_model_name.to_s) end |
Instance Method Details
#map_model(_model) ⇒ Object
Use the map_model method within the form implementations to map any custom form-specific attributes from the model to the form.
105 |
# File 'lib/decidim/attribute_object/form.rb', line 105 def map_model(_model); end |
#persisted? ⇒ Boolean
84 85 86 |
# File 'lib/decidim/attribute_object/form.rb', line 84 def persisted? id.present? && id.to_i.positive? end |
#to_key ⇒ Object
88 89 90 |
# File 'lib/decidim/attribute_object/form.rb', line 88 def to_key [id] end |
#to_model ⇒ Object
Required for the active model naming to work correctly to form the HTML class attributes for the form elements (e.g. edit_account instead of edit_account_form).
95 96 97 |
# File 'lib/decidim/attribute_object/form.rb', line 95 def to_model self end |
#to_param ⇒ Object
99 100 101 |
# File 'lib/decidim/attribute_object/form.rb', line 99 def to_param id.to_s end |
#valid?(_context = nil) ⇒ Boolean
Although we are running the nested attributes validations through the NestedValidator, we still need to check for the errors in the nested attributes after the main validations are run in case the main validations are adding errors to some of the nested attributes.
An example of such form is the Decidim::Budgets::Admin::ComponentForm which adds errors to the sub-attribute “settings” during its own validations. Because these errors are not added to the main form object, the main form object would be interpreted as valid without checking the sub-attribute validations.
This preserves the backwards compatibility with Rectify::Form which did the validations in this order and fails the main record validation in case one of the nested attributes is not valid. This is needed e.g. for the customized component validations (e.g. Budgets component form).
147 148 149 150 151 152 153 154 155 156 157 |
# File 'lib/decidim/attribute_object/form.rb', line 147 def valid?(_context = nil) super && self.class.attribute_types.none? do |name, type| value = public_send(name) if value.is_a?(Decidim::AttributeObject::Model) || (type.respond_to?(:validate_nested?) && type.validate_nested?) _value_has_errors?(value) else false end end end |
#with_context(new_context) ⇒ Object
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
# File 'lib/decidim/attribute_object/form.rb', line 107 def with_context(new_context) @context = if new_context.is_a?(Hash) OpenStruct.new(new_context) else new_context end attributes.each do |_name, value| case value when Array value.each do |v| next unless v.respond_to?(:with_context) v.with_context(context) end else next unless value.respond_to?(:with_context) value.with_context(context) end end self end |