Class: Lifeform::Form
- Inherits:
-
Phlex::HTML
- Object
- Phlex::HTML
- Lifeform::Form
- Includes:
- CapturingRenderable
- Defined in:
- lib/lifeform/form.rb
Overview
A form object which stores field definitions and can be rendered as a component
Constant Summary collapse
- MODEL_PATH_HELPER =
:polymorphic_path
Instance Attribute Summary collapse
- #emit_form_tag ⇒ Boolean readonly
- #library ⇒ Class<Libraries::Default> readonly
- #model ⇒ Object readonly
- #parameters ⇒ Hash readonly
- #parent_name ⇒ Boolean readonly
- #url ⇒ String readonly
Class Method Summary collapse
- .field(name, type: :text, library: self.library, **parameters) ⇒ Object
- .fields ⇒ Hash<Symbol, FieldDefinition>
- .inherited(subclass) ⇒ Object
- .library(library_name = nil) ⇒ Object
- .name_of_model(model) ⇒ Object
- .param_keys ⇒ Array<Symbol>
- .param_string_keys ⇒ Array<String>
- .parameters_to_attributes(kwargs) ⇒ Object
- .process_value(key, value) ⇒ Object
- .subform(name, klass, parent_name: nil) ⇒ Object
- .subforms ⇒ Object
-
.t ⇒ Object
Helper to point to ‘I18n.t` method.
Instance Method Summary collapse
-
#add_authenticity_token ⇒ Object
rubocop:disable Metrics/AbcSize.
- #attributes ⇒ Object
- #auto_render_fields ⇒ Object
- #field(name, **field_parameters) ⇒ Object
-
#initialize(model = nil, url: nil, library: self.class.library, emit_form_tag: true, parent_name: nil, **parameters) ⇒ Form
constructor
rubocop:disable Metrics/ParameterLists.
- #subform(name, model = nil) ⇒ Object
-
#template(&block) ⇒ Object
rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity.
- #verify_method ⇒ Object
Methods included from CapturingRenderable
Constructor Details
#initialize(model = nil, url: nil, library: self.class.library, emit_form_tag: true, parent_name: nil, **parameters) ⇒ Form
rubocop:disable Metrics/ParameterLists
119 120 121 122 123 124 125 126 127 128 129 130 |
# File 'lib/lifeform/form.rb', line 119 def initialize( # rubocop:disable Metrics/ParameterLists model = nil, url: nil, library: self.class.library, emit_form_tag: true, parent_name: nil, **parameters ) @model, @url, @library_name, @parameters, @emit_form_tag, @parent_name = model, url, library, parameters, emit_form_tag, parent_name @library = Libraries.const_get(@library_name.to_s.classify) @subform_instances = {} @method = parameters[:method] ||= model.respond_to?(:persisted?) && model.persisted? ? :patch : :post parameters[:accept_charset] ||= "UTF-8" verify_method end |
Instance Attribute Details
#emit_form_tag ⇒ Boolean (readonly)
114 115 116 |
# File 'lib/lifeform/form.rb', line 114 def emit_form_tag @emit_form_tag end |
#library ⇒ Class<Libraries::Default> (readonly)
108 109 110 |
# File 'lib/lifeform/form.rb', line 108 def library @library end |
#model ⇒ Object (readonly)
102 103 104 |
# File 'lib/lifeform/form.rb', line 102 def model @model end |
#parameters ⇒ Hash (readonly)
111 112 113 |
# File 'lib/lifeform/form.rb', line 111 def parameters @parameters end |
#parent_name ⇒ Boolean (readonly)
117 118 119 |
# File 'lib/lifeform/form.rb', line 117 def parent_name @parent_name end |
#url ⇒ String (readonly)
105 106 107 |
# File 'lib/lifeform/form.rb', line 105 def url @url end |
Class Method Details
.field(name, type: :text, library: self.library, **parameters) ⇒ Object
33 34 35 36 |
# File 'lib/lifeform/form.rb', line 33 def field(name, type: :text, library: self.library, **parameters) parameters[:name] = name.to_sym fields[name] = FieldDefinition.new(type, Libraries.const_get(library.to_s.classify), parameters) end |
.fields ⇒ Hash<Symbol, FieldDefinition>
25 26 27 |
# File 'lib/lifeform/form.rb', line 25 def fields @fields ||= {} end |
.inherited(subclass) ⇒ Object
14 15 16 17 |
# File 'lib/lifeform/form.rb', line 14 def inherited(subclass) super subclass.library library end |
.library(library_name = nil) ⇒ Object
42 43 44 45 |
# File 'lib/lifeform/form.rb', line 42 def library(library_name = nil) @library = library_name.to_sym if library_name @library ||= :default end |
.name_of_model(model) ⇒ Object
79 80 81 82 83 84 85 86 87 88 |
# File 'lib/lifeform/form.rb', line 79 def name_of_model(model) return "" if model.nil? if model.respond_to?(:to_model) model.to_model.model_name.param_key else # Or just use basic underscore model.class.name.underscore.tr("/", "_") end end |
.param_keys ⇒ Array<Symbol>
91 92 93 |
# File 'lib/lifeform/form.rb', line 91 def param_keys fields.keys end |
.param_string_keys ⇒ Array<String>
96 97 98 |
# File 'lib/lifeform/form.rb', line 96 def param_string_keys fields.keys.map(&:to_s) end |
.parameters_to_attributes(kwargs) ⇒ Object
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/lifeform/form.rb', line 63 def parameters_to_attributes(kwargs) attributes = {} kwargs.each do |key, value| case value when Hash value.each do |inner_key, inner_value| attributes[:"#{key}_#{inner_key}"] = process_value(inner_key, inner_value) end else attributes[key] = process_value(key, value) unless value.nil? end end attributes end |
.process_value(key, value) ⇒ Object
47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
# File 'lib/lifeform/form.rb', line 47 def process_value(key, value) return value if key == :if case value when TrueClass key.to_s when FalseClass nil when Symbol, Integer value.to_s else value end end |
.subform(name, klass, parent_name: nil) ⇒ Object
38 39 40 |
# File 'lib/lifeform/form.rb', line 38 def subform(name, klass, parent_name: nil) subforms[name.to_sym] = { class: klass, parent_name: parent_name } end |
.subforms ⇒ Object
29 30 31 |
# File 'lib/lifeform/form.rb', line 29 def subforms @subforms ||= {} end |
.t ⇒ Object
Helper to point to ‘I18n.t` method
20 21 22 |
# File 'lib/lifeform/form.rb', line 20 def t(...) I18n.t(...) end |
Instance Method Details
#add_authenticity_token ⇒ Object
rubocop:disable Metrics/AbcSize
148 149 150 151 152 153 154 155 156 157 158 159 |
# File 'lib/lifeform/form.rb', line 148 def add_authenticity_token # rubocop:disable Metrics/AbcSize if helpers.respond_to?(:token_tag, true) # Rails helpers.send(:token_tag, nil, form_options: { action: parameters[:action].to_s, method: parameters[:method].to_s.downcase }) elsif helpers.respond_to?(:csrf_tag, true) # Roda helpers.send(:csrf_tag, parameters[:action].to_s, @method.to_s) else raise Lifeform::Error, "Missing token tag helper. Override `add_authenticity_token' in your Form object" end end |
#attributes ⇒ Object
161 162 163 |
# File 'lib/lifeform/form.rb', line 161 def attributes @attributes ||= self.class.parameters_to_attributes(parameters) end |
#auto_render_fields ⇒ Object
194 195 196 |
# File 'lib/lifeform/form.rb', line 194 def auto_render_fields self.class.fields.map { |k, _v| render(field(k)) } end |
#field(name, **field_parameters) ⇒ Object
165 166 167 168 169 170 171 172 173 |
# File 'lib/lifeform/form.rb', line 165 def field(name, **field_parameters) # @type [FieldDefinition] field_definition = self.class.fields[name.to_sym] # @type [Class<Libraries::Default>] field_library = field_definition.library field_library.object_for_field_definition( self, field_definition, self.class.parameters_to_attributes(field_parameters) ) end |
#subform(name, model = nil) ⇒ Object
175 176 177 178 179 180 181 |
# File 'lib/lifeform/form.rb', line 175 def subform(name, model = nil) @subform_instances[name.to_sym] ||= self.class.subforms[name.to_sym][:class].new( model, emit_form_tag: false, parent_name: self.class.subforms[name.to_sym][:parent_name] || self.class.name_of_model(self.model) ) end |
#template(&block) ⇒ Object
rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
183 184 185 186 187 188 189 190 191 192 |
# File 'lib/lifeform/form.rb', line 183 def template(&block) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity form_tag = library::FORM_TAG parameters[:action] ||= url || (model ? helpers.send(self.class.const_get(:MODEL_PATH_HELPER), model) : nil) send(form_tag, **attributes) do unsafe_raw(add_authenticity_token) unless parameters[:method].to_s.downcase == "get" unsafe_raw @method_tag&.() || "" block ? yield_content(&block) : auto_render_fields end end |
#verify_method ⇒ Object
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 |
# File 'lib/lifeform/form.rb', line 132 def verify_method return if %w[get post].include?(parameters[:method].to_s.downcase) @method_tag = Class.new(Phlex::HTML) do # TODO: break this out into a real component def initialize(method:) @method = method end def template input type: "hidden", name: "_method", value: @method, autocomplete: "off" end end.new(method: @parameters[:method].to_s.downcase) parameters[:method] = :post end |