Class: Lifeform::Form
- Inherits:
-
Object
- Object
- Lifeform::Form
- Extended by:
- Sequel::Inflections, Streamlined::Helpers
- Includes:
- Streamlined::Renderable
- 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
Class Attribute Summary collapse
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
- .configuration ⇒ Object
- .disable_csrf_protection! ⇒ Object
- .field(name, type: :text, library: self.library, **parameters) ⇒ Object
- .fields(&block) ⇒ Hash<Symbol, FieldDefinition>
-
.fragment(name) {|form| ... } ⇒ Object
Add an HTML fragment which will be auto-rendered or manually rendered like any field.
- .inherited(subclass) ⇒ Object
- .initialize_field_definitions! ⇒ 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
- #attributes ⇒ Object
- #auto_render_fields ⇒ Object
- #configuration ⇒ Object
- #field(name, **field_parameters) ⇒ Object
- #fragment(name) ⇒ Object
- #include_authenticity_token? ⇒ Boolean
-
#initialize(model = nil, url: nil, library: self.class.library, emit_form_tag: true, parent_name: nil, view_context: nil, **parameters) ⇒ Form
constructor
rubocop:disable Metrics/ParameterLists.
- #render(field_object) ⇒ Object
- #subform(name, model = nil) ⇒ Object
-
#template(&block) ⇒ Object
rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity.
- #verify_method ⇒ Object
Constructor Details
#initialize(model = nil, url: nil, library: self.class.library, emit_form_tag: true, parent_name: nil, view_context: nil, **parameters) ⇒ Form
rubocop:disable Metrics/ParameterLists
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 |
# File 'lib/lifeform/form.rb', line 155 def initialize( # rubocop:disable Metrics/ParameterLists model = nil, url: nil, library: self.class.library, emit_form_tag: true, parent_name: nil, view_context: 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(self.class.send(:camelize, @library_name)) @subform_instances = {} @_view_context = view_context self.class.initialize_field_definitions! @method = parameters[:method] ||= model.respond_to?(:persisted?) && model.persisted? ? :patch : :post parameters[:accept_charset] ||= "UTF-8" verify_method end |
Class Attribute Details
.rodauth ⇒ Object
30 |
# File 'lib/lifeform/form.rb', line 30 def rodauth = Form.instance_variable_get(:@rodauth) |
Instance Attribute Details
#emit_form_tag ⇒ Boolean (readonly)
150 151 152 |
# File 'lib/lifeform/form.rb', line 150 def emit_form_tag @emit_form_tag end |
#library ⇒ Class<Libraries::Default> (readonly)
144 145 146 |
# File 'lib/lifeform/form.rb', line 144 def library @library end |
#model ⇒ Object (readonly)
138 139 140 |
# File 'lib/lifeform/form.rb', line 138 def model @model end |
#parameters ⇒ Hash (readonly)
147 148 149 |
# File 'lib/lifeform/form.rb', line 147 def parameters @parameters end |
#parent_name ⇒ Boolean (readonly)
153 154 155 |
# File 'lib/lifeform/form.rb', line 153 def parent_name @parent_name end |
#url ⇒ String (readonly)
141 142 143 |
# File 'lib/lifeform/form.rb', line 141 def url @url end |
Class Method Details
.configuration ⇒ Object
32 |
# File 'lib/lifeform/form.rb', line 32 def configuration = @configuration ||= HashWithDotAccess::Hash.new |
.disable_csrf_protection! ⇒ Object
34 |
# File 'lib/lifeform/form.rb', line 34 def disable_csrf_protection! = configuration.disable_csrf_protection = true |
.field(name, type: :text, library: self.library, **parameters) ⇒ Object
53 54 55 56 |
# File 'lib/lifeform/form.rb', line 53 def field(name, type: :text, library: self.library, **parameters) parameters[:name] = name.to_sym fields[name] = FieldDefinition.new(type, Libraries.const_get(camelize(library)), parameters) end |
.fields(&block) ⇒ Hash<Symbol, FieldDefinition>
38 39 40 41 42 43 |
# File 'lib/lifeform/form.rb', line 38 def fields(&block) @fields ||= {} @fields_setup_block = block if block @fields end |
.fragment(name) {|form| ... } ⇒ Object
Add an HTML fragment which will be auto-rendered or manually rendered like any field. Use Streamlined helpers inside a squiggly heredoc passed via the block which will be executed within the view context (requires it have ‘include Streamlined::Helpers`)
76 |
# File 'lib/lifeform/form.rb', line 76 def fragment(name, &block) = field(:"__#{name}", library: :default, type: :html, body: block) |
.inherited(subclass) ⇒ Object
19 20 21 22 |
# File 'lib/lifeform/form.rb', line 19 def inherited(subclass) super subclass.library library end |
.initialize_field_definitions! ⇒ Object
45 46 47 48 49 |
# File 'lib/lifeform/form.rb', line 45 def initialize_field_definitions! return unless @fields_setup_block @fields_setup_block.(configuration) end |
.library(library_name = nil) ⇒ Object
82 83 84 85 |
# File 'lib/lifeform/form.rb', line 82 def library(library_name = nil) @library = library_name.to_sym if library_name @library ||= :default end |
.name_of_model(model) ⇒ Object
119 120 121 122 123 124 125 126 127 128 |
# File 'lib/lifeform/form.rb', line 119 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 underscore(model.class.name).tr("/", "_") end end |
.param_keys ⇒ Array<Symbol>
131 |
# File 'lib/lifeform/form.rb', line 131 def param_keys = fields.keys |
.param_string_keys ⇒ Array<String>
134 |
# File 'lib/lifeform/form.rb', line 134 def param_string_keys = fields.keys.map(&:to_s) |
.parameters_to_attributes(kwargs) ⇒ Object
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
# File 'lib/lifeform/form.rb', line 103 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
87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
# File 'lib/lifeform/form.rb', line 87 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
78 79 80 |
# File 'lib/lifeform/form.rb', line 78 def subform(name, klass, parent_name: nil) subforms[name.to_sym] = { class: klass, parent_name: parent_name } end |
.subforms ⇒ Object
51 |
# File 'lib/lifeform/form.rb', line 51 def subforms = @subforms ||= {} |
.t ⇒ Object
Helper to point to ‘I18n.t` method
25 |
# File 'lib/lifeform/form.rb', line 25 def t(...) = I18n.t(...) |
Instance Method Details
#add_authenticity_token ⇒ Object
193 194 195 196 197 198 199 200 201 202 203 204 |
# File 'lib/lifeform/form.rb', line 193 def add_authenticity_token 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
208 209 210 |
# File 'lib/lifeform/form.rb', line 208 def attributes @attributes ||= self.class.parameters_to_attributes(parameters) end |
#auto_render_fields ⇒ Object
248 |
# File 'lib/lifeform/form.rb', line 248 def auto_render_fields = html_map(self.class.fields) { |k, _v| render(field(k)) } |
#configuration ⇒ Object
177 |
# File 'lib/lifeform/form.rb', line 177 def configuration = self.class.configuration |
#field(name, **field_parameters) ⇒ Object
212 213 214 215 216 217 218 219 220 |
# File 'lib/lifeform/form.rb', line 212 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 |
#fragment(name) ⇒ Object
222 |
# File 'lib/lifeform/form.rb', line 222 def fragment(name, **) = field(:"__#{name}", **) |
#include_authenticity_token? ⇒ Boolean
206 |
# File 'lib/lifeform/form.rb', line 206 def include_authenticity_token? = !configuration.disable_csrf_protection |
#render(field_object) ⇒ Object
250 251 252 |
# File 'lib/lifeform/form.rb', line 250 def render(field_object) field_object.render_in(helpers) end |
#subform(name, model = nil) ⇒ Object
224 225 226 227 228 229 230 231 |
# File 'lib/lifeform/form.rb', line 224 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), view_context: helpers ) end |
#template(&block) ⇒ Object
rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
233 234 235 236 237 238 239 240 241 242 243 244 245 246 |
# File 'lib/lifeform/form.rb', line 233 def template(&block) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity form_tag = library::FORM_TAG parameters[:action] ||= url || (model ? helpers.send(self.class.const_get(:MODEL_PATH_HELPER), model) : nil) output_token = include_authenticity_token? && parameters[:method].to_s.casecmp("get").zero?.! html -> { " <\#{form_tag} \#{html_attributes attributes}>\n \#{add_authenticity_token if output_token}\n \#{@method_tag&.() || \"\"}\n \#{block ? capture(self, &block) : auto_render_fields}\n </\#{form_tag}>\n HTML\n }\nend\n" # rubocop:disable Bridgetown/InsecureHeredoc |
#verify_method ⇒ Object
179 180 181 182 183 184 185 186 187 188 189 190 191 |
# File 'lib/lifeform/form.rb', line 179 def verify_method return if %w[get post].include?(parameters[:method].to_s.downcase) method_value = @parameters[:method].to_s.downcase @method_tag = -> { " <input type=\"hidden\" name=\"_method\" value=\"\#{text -> { method_value }}\" autocomplete=\"off\">\n HTML\n }\n\n parameters[:method] = :post\nend\n" |