class Readymade::Form
Constants
- PERMITTED_ATTRIBUTES
- REQUIRED_ATTRIBUTES
Attributes
args[RW]
nested_forms[R]
list nested_forms
in child form in order to validate them
params[RW]
record[RW]
Public Class Methods
form_options(**args)
click to toggle source
@form = Items::Forms::Create.form_options(company: current_company) f.association :item_category, collection: @form, required: @form.required?(:item_category)
# File lib/readymade/form.rb, line 164 def self.form_options(**args) Readymade::Form::FormOptions.new(**args.merge!(form_class: self)) end
new(params, **args)
click to toggle source
Calls superclass method
# File lib/readymade/form.rb, line 14 def initialize(params, **args) @params = params @record = args[:record] @args = args @nested_forms = [] @required_attributes = Array(args[:required]).presence @permitted_attributes = (Array(@required_attributes) + Array(args[:permitted])).presence parse_datetime_params # Slice all attributes which is not required by form # to omit save of unpredictable params @params&.slice!(*permitted_attributes) # if permitted_attributes.present? # dynamically creates attr accessors @permitted_attributes&.each do |key| singleton_class.class_eval do attr_accessor key end end # automatically validates all REQUIRED_ATTRIBUTES singleton_class.validates(*required_attributes, presence: true) if required_attributes.present? build_nested_forms super(@params) end
Public Instance Methods
build_nested_forms()
click to toggle source
# File lib/readymade/form.rb, line 51 def build_nested_forms nested_forms_mapping.each do |attr, form_class| next if params[attr].blank? if form_class.is_a?(Array) n_forms = if params[attr].is_a?(Hash) # { 0 => {id: 1, name: 'my name'}, 1 => { id: 2, name: 'other name' }} params[attr].map { |_i, attrs| form_class[0].new(attrs) } else # [{id: 1, name: 'my name'}, { id: 2, name: 'other name' }] params[attr].map { |attrs| form_class[0].new(attrs) } end @nested_forms.push(*n_forms) define_singleton_method("#{attr}_forms") { n_forms } else @nested_forms.push(f = form_class.new(params[attr])) define_singleton_method("#{attr}_form") { f } end end end
datetime_params()
click to toggle source
list datetime_params
in child form in order to parse datetime properly
# File lib/readymade/form.rb, line 135 def datetime_params [] end
humanized_name()
click to toggle source
# File lib/readymade/form.rb, line 111 def humanized_name self.class.name.underscore.split('/')[0] end
nested_forms_mapping()
click to toggle source
define nested forms in format { attr_name: MyFormClass } use the following syntax if attribute is a collection: { attr_collection_name: [MyFormClass] }
# File lib/readymade/form.rb, line 144 def nested_forms_mapping {} end
parse_datetime_params()
click to toggle source
uses datetime_params
to fix the following issue: stackoverflow.com/questions/5073756/where-is-the-rails-method-that-converts-data-from-datetime-select-into-a-datet
# File lib/readymade/form.rb, line 117 def parse_datetime_params datetime_params.each do |param| next if @params[param].present? # set datetime to nil if year is blank if @params["#{param}(1i)"].blank? @params[param] = nil next end @params[param] = DateTime.new(*(1..5).map { |i| @params["#{param}(#{i}i)"].to_i }) end rescue ArgumentError nil end
permitted_attributes()
click to toggle source
# File lib/readymade/form.rb, line 43 def permitted_attributes @permitted_attributes ||= self.class::PERMITTED_ATTRIBUTES end
required_attributes()
click to toggle source
# File lib/readymade/form.rb, line 47 def required_attributes @required_attributes ||= self.class::REQUIRED_ATTRIBUTES end
sync_errors(from: self, to: record)
click to toggle source
sync errors from form to record or vice-versa
# File lib/readymade/form.rb, line 92 def sync_errors(from: self, to: record) return if [from, to].any?(&:blank?) if Rails.version.to_f > 6.0 from.errors.messages.each do |key, values| Array.wrap(values).uniq.each do |uv| to.errors.add(key, uv) end end else errors = from.errors.instance_variable_get('@messages').to_h errors.merge!(to.errors.instance_variable_get('@messages').to_h) to.errors.instance_variable_set('@messages', errors) to.errors.messages.transform_values!(&:uniq) # Does not work with rails 6.1 end rescue FrozenError => _e end
sync_nested_errors(nested_forms)
click to toggle source
copy errors from nested forms into parent form
# File lib/readymade/form.rb, line 81 def sync_nested_errors(nested_forms) nested_forms.each do |n_form| n_form.errors.each do |code, text| errors.add("#{n_form.humanized_name}.#{code}", text) end end false end
validate()
click to toggle source
Calls superclass method
# File lib/readymade/form.rb, line 72 def validate super && validate_nested(*nested_forms) end
validate_nested(*nested_forms)
click to toggle source
# File lib/readymade/form.rb, line 76 def validate_nested(*nested_forms) nested_forms.compact.map(&:validate).all? || sync_nested_errors(nested_forms) end