Class: Kadmin::Form
- Inherits:
-
Object
- Object
- Kadmin::Form
- Extended by:
- ActiveModel::Callbacks, ActiveModel::Translation
- Includes:
- ActiveModel::Validations, ActiveRecord::AttributeAssignment
- Defined in:
- app/components/kadmin/form.rb
Overview
Parsing is done by using attribute setters. If you have an attribute called name, then add a reader/writer for it, name and name=, and perform the parsing in name=. If there is no parsing to be done, you can simply delegate the method to the underlying model.
If the attribute is a nested form, in the writer, simply instantiate that form, and pass the attributes on to it, then update the model’s association (if any) to reflect the changes.
Validation is performed like on a normal model or ActiveRecord object. If you have no extra validation to perform than that of the model, simply delegate the validate and valid? methods to the model.
To use nested forms, you need to add a reader and a writer. For example, for a form called Person, with potentially X nested Person forms as children, you would have:
Instance Attribute Summary collapse
-
#model ⇒ ActiveModel::Model
readonly
Underlying model to populate.
Attributes assignment/manipulation collapse
-
#sanitize_for_mass_assignment(attributes) ⇒ Object
For now, we overload the method to accept all attributes.
Persistence collapse
Class Method Summary collapse
-
.delegate_association(association, to:) ⇒ Object
Delegates a specified associations to other another form object.
-
.delegate_attributes(*attributes) ⇒ Object
Delegates the list of attributes to the model, both readers and writers.
Instance Method Summary collapse
-
#initialize(model) ⇒ Form
constructor
A new instance of Form.
- #to_model ⇒ Object
Constructor Details
#initialize(model) ⇒ Form
Returns a new instance of Form.
47 48 49 50 51 52 |
# File 'app/components/kadmin/form.rb', line 47 def initialize(model) @errors = ActiveModel::Errors.new(self) @model = model @form_input = {} @associated_forms = Hash.new { |hash, key| hash[key] = [] } end |
Instance Attribute Details
#model ⇒ ActiveModel::Model (readonly)
Returns underlying model to populate.
43 44 45 |
# File 'app/components/kadmin/form.rb', line 43 def model @model end |
Class Method Details
.delegate_association(association, to:) ⇒ Object
Delegates a specified associations to other another form object
102 103 104 105 106 107 108 109 |
# File 'app/components/kadmin/form.rb', line 102 def delegate_association(association, to:) # add a reader attribute class_eval <<~METHOD, __FILE__, __LINE__ + 1 def #{association}(index = 0) return associated_form('#{association}', form_class: '#{to}', index: index) end METHOD end |
.delegate_attributes(*attributes) ⇒ Object
Delegates the list of attributes to the model, both readers and writers. If the attribute value passed is a hash and not a symbol, assumes it is a hash of one key, whose value is an array contained :reader, :writer, or both.
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
# File 'app/components/kadmin/form.rb', line 82 def delegate_attributes(*attributes) delegates = attributes.each_with_object([]) do |attribute, acc| case attribute when Hash key, value = attribute.first acc << key if value.include?(:reader) acc << "#{key}=" if value.include?(:writer) when Symbol, String acc.push(attribute, "#{attribute}=") else raise(ArgumentError, 'Attribute must be one of: Hash, Symbol, String') end end delegate(*delegates, to: :model) end |
Instance Method Details
#sanitize_for_mass_assignment(attributes) ⇒ Object
For now, we overload the method to accept all attributes. This is removed in Rails 5, so once we upgrade we can remove the overload.
67 68 69 |
# File 'app/components/kadmin/form.rb', line 67 def sanitize_for_mass_assignment(attributes) return attributes end |
#save ⇒ Object
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 |
# File 'app/components/kadmin/form.rb', line 175 def save saved = false # TODO: Check if the top level transaction is necessary here # run_callbacks is already a transaction? @model.class.transaction do run_callbacks :save do saved = @model.save @associated_forms.values.flatten do |form| saved &&= form.save end raise ActiveRecord::Rollback unless saved end end return saved end |
#save! ⇒ Object
193 194 195 196 197 198 199 200 201 202 203 204 205 |
# File 'app/components/kadmin/form.rb', line 193 def save! saved = false @model.class.transaction do run_callbacks :save do saved = @model.save! @associated_forms.values.flatten.each do |form| saved &&= form.save! # no need to raise anything, save! will do so end end end return saved end |
#to_model ⇒ Object
54 55 56 |
# File 'app/components/kadmin/form.rb', line 54 def to_model return @model end |