Class: Bureaucrat::Forms::Form
- Inherits:
-
Object
- Object
- Bureaucrat::Forms::Form
- Includes:
- Utils
- Defined in:
- lib/bureaucrat/forms.rb
Overview
Base class for forms. Forms are a collection of fields with data that knows how to render and validate itself.
Bound vs Unbound forms
A form is ‘bound’ if it was initialized with a set of data for its fields, otherwise it is ‘unbound’. Only bound forms can be validated. Unbound forms always respond with false to valid?
and return an empty list of errors.
Direct Known Subclasses
Constant Summary
Constants included from Utils
Instance Attribute Summary collapse
-
#auto_id ⇒ Object
Format string for field id generator.
-
#cleaned_data ⇒ Object
Validated and cleaned data.
-
#data ⇒ Object
Data associated to this form => value.
-
#error_class ⇒ Object
Error object class for this form.
-
#error_css_class ⇒ Object
Required class for this form.
-
#fields ⇒ Object
Fields belonging to this form.
-
#files ⇒ Object
TODO: complete implementation.
-
#initial ⇒ Object
Hash of => initial_value.
-
#required_css_class ⇒ Object
Required class for this form.
Class Method Summary collapse
-
.base_fields ⇒ Object
Fields associated to the form class.
-
.field(name, field_obj) ⇒ Object
Declares a named field to be used on this form.
-
.inherited(c) ⇒ Object
Copy data to the child class.
Instance Method Summary collapse
-
#[](name) ⇒ Object
Access a named field.
-
#add_initial_prefix(field_name) ⇒ Object
Generates an initial-prefix for field named
field_name
. -
#add_prefix(field_name) ⇒ Object
Generates a prefix for field named
field_name
. -
#bound? ⇒ Boolean
Checks if this form was initialized with data.
-
#changed? ⇒ Boolean
true if the form has data that isn’t equal to its initial data.
-
#changed_data ⇒ Object
List names for fields that have changed data.
-
#clean ⇒ Object
Performs the last step of validations on the form, override in subclasses to customize behaviour.
-
#each ⇒ Object
Iterates over the fields.
-
#empty_permitted? ⇒ Boolean
true if the form is valid when empty.
-
#errors ⇒ Object
Errors for this forms (runs validations).
-
#full_clean ⇒ Object
Runs all the validations for this form.
-
#hidden_fields ⇒ Object
List of hidden fields.
-
#initialize(data = nil, options = {}) ⇒ Form
constructor
Instantiates a new form bound to the passed data (or unbound if data is nil).
-
#label_attributes(name, field) ⇒ Object
Attributes for labels, override in subclasses to customize behaviour.
-
#multipart? ⇒ Boolean
true if this form contains fields that require the form to be multipart.
-
#non_field_errors ⇒ Object
Returns the list of errors that aren’t associated to a specific field.
-
#populate_object(object) ⇒ Object
Populates the passed object’s attributes with data from the fields.
-
#valid? ⇒ Boolean
Perform validation and returns true if there are no errors.
-
#visible_fields ⇒ Object
List of visible fields.
Methods included from Utils
#blank_value?, #conditional_escape, #escape, #flatatt, #format_string, #make_bool, #make_float, #mark_safe, #pretty_name
Constructor Details
#initialize(data = nil, options = {}) ⇒ Form
Instantiates a new form bound to the passed data (or unbound if data is nil)
data
is a hash of => value for this form to be bound (will be unbound if nil)
Possible options are:
:prefix prefix that will be used for fields when rendered
:auto_id format string that will be used when generating
field ids (default: 'id_%s')
:initial hash of {field_name => default_value}
(doesn't make a form bound)
:error_class class used to represent errors (default: ErrorList)
:label_suffix suffix string that will be appended to labels' text
(default: ':')
:empty_permitted boolean value that specifies if this form is valid
when empty
206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 |
# File 'lib/bureaucrat/forms.rb', line 206 def initialize(data=nil, ={}) @is_bound = !data.nil? @data = StringAccessHash.new(data || {}) @files = .fetch(:files, {}) @auto_id = .fetch(:auto_id, 'id_%s') @prefix = [:prefix] @initial = StringAccessHash.new(.fetch(:initial, {})) @error_class = .fetch(:error_class, Fields::ErrorList) @label_suffix = .fetch(:label_suffix, ':') @empty_permitted = .fetch(:empty_permitted, false) @errors = nil @changed_data = nil @fields = self.class.base_fields.dup @fields.each { |key, value| @fields[key] = value.dup } end |
Instance Attribute Details
#auto_id ⇒ Object
Format string for field id generator
174 175 176 |
# File 'lib/bureaucrat/forms.rb', line 174 def auto_id @auto_id end |
#cleaned_data ⇒ Object
Validated and cleaned data
182 183 184 |
# File 'lib/bureaucrat/forms.rb', line 182 def cleaned_data @cleaned_data end |
#data ⇒ Object
Data associated to this form => value
178 179 180 |
# File 'lib/bureaucrat/forms.rb', line 178 def data @data end |
#error_class ⇒ Object
Error object class for this form
168 169 170 |
# File 'lib/bureaucrat/forms.rb', line 168 def error_class @error_class end |
#error_css_class ⇒ Object
Required class for this form
172 173 174 |
# File 'lib/bureaucrat/forms.rb', line 172 def error_css_class @error_css_class end |
#fields ⇒ Object
Fields belonging to this form
184 185 186 |
# File 'lib/bureaucrat/forms.rb', line 184 def fields @fields end |
#files ⇒ Object
TODO: complete implementation
180 181 182 |
# File 'lib/bureaucrat/forms.rb', line 180 def files @files end |
#initial ⇒ Object
Hash of => initial_value
176 177 178 |
# File 'lib/bureaucrat/forms.rb', line 176 def initial @initial end |
#required_css_class ⇒ Object
Required class for this form
170 171 172 |
# File 'lib/bureaucrat/forms.rb', line 170 def required_css_class @required_css_class end |
Class Method Details
.base_fields ⇒ Object
Fields associated to the form class
152 153 154 |
# File 'lib/bureaucrat/forms.rb', line 152 def self.base_fields @base_fields ||= {} end |
.field(name, field_obj) ⇒ Object
Declares a named field to be used on this form.
157 158 159 |
# File 'lib/bureaucrat/forms.rb', line 157 def self.field(name, field_obj) base_fields[name] = field_obj end |
.inherited(c) ⇒ Object
Copy data to the child class
162 163 164 165 |
# File 'lib/bureaucrat/forms.rb', line 162 def self.inherited(c) super(c) c.instance_variable_set(:@base_fields, base_fields.dup) end |
Instance Method Details
#[](name) ⇒ Object
Access a named field
231 232 233 234 |
# File 'lib/bureaucrat/forms.rb', line 231 def [](name) field = @fields[name] or return nil BoundField.new(self, field, name) end |
#add_initial_prefix(field_name) ⇒ Object
Generates an initial-prefix for field named field_name
253 254 255 |
# File 'lib/bureaucrat/forms.rb', line 253 def add_initial_prefix(field_name) "initial-#{add_prefix(field_name)}" end |
#add_prefix(field_name) ⇒ Object
Generates a prefix for field named field_name
248 249 250 |
# File 'lib/bureaucrat/forms.rb', line 248 def add_prefix(field_name) @prefix ? "#{@prefix}-#{field_name}" : field_name end |
#bound? ⇒ Boolean
Checks if this form was initialized with data.
187 |
# File 'lib/bureaucrat/forms.rb', line 187 def bound? ; @is_bound; end |
#changed? ⇒ Boolean
true if the form has data that isn’t equal to its initial data
314 315 316 |
# File 'lib/bureaucrat/forms.rb', line 314 def changed? changed_data && !changed_data.empty? end |
#changed_data ⇒ Object
List names for fields that have changed data
319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 |
# File 'lib/bureaucrat/forms.rb', line 319 def changed_data if @changed_data.nil? @changed_data = [] @fields.each do |name, field| prefixed_name = add_prefix(name) data_value = field.. value_from_formdata(@data, prefixed_name) if !field.show_hidden_initial initial_value = @initial.fetch(name, field.initial) else initial_prefixed_name = add_initial_prefix(name) = field..new initial_value = . value_from_formdata(@data, initial_prefixed_name) end @changed_data << name if field..has_changed?(initial_value, data_value) end end @changed_data end |
#clean ⇒ Object
Performs the last step of validations on the form, override in subclasses to customize behaviour.
309 310 311 |
# File 'lib/bureaucrat/forms.rb', line 309 def clean @cleaned_data end |
#each ⇒ Object
Iterates over the fields
224 225 226 227 228 |
# File 'lib/bureaucrat/forms.rb', line 224 def each @fields.each do |name, field| yield BoundField.new(self, field, name) end end |
#empty_permitted? ⇒ Boolean
true if the form is valid when empty
258 259 260 |
# File 'lib/bureaucrat/forms.rb', line 258 def empty_permitted? @empty_permitted end |
#errors ⇒ Object
Errors for this forms (runs validations)
237 238 239 240 |
# File 'lib/bureaucrat/forms.rb', line 237 def errors full_clean if @errors.nil? @errors end |
#full_clean ⇒ Object
Runs all the validations for this form. If the form is invalid the list of errors is populated, if it is valid, cleaned_data is populated
270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 |
# File 'lib/bureaucrat/forms.rb', line 270 def full_clean @errors = Fields::ErrorHash.new return unless bound? @cleaned_data = StringAccessHash.new return if empty_permitted? && !changed? @fields.each do |name, field| value = field.. value_from_formdata(@data, add_prefix(name)) begin if field.is_a?(Fields::FileField) initial = @initial.fetch(name, field.initial) @cleaned_data[name] = field.clean(value, initial) else @cleaned_data[name] = field.clean(value) end clean_method = 'clean_%s' % name @cleaned_data[name] = send(clean_method) if respond_to?(clean_method) rescue ValidationError => e @errors[name] = e. @cleaned_data.delete(name) end end begin @cleaned_data = clean rescue ValidationError => e @errors[:__NON_FIELD_ERRORS] = e. end @cleaned_data = nil if @errors && !@errors.empty? end |
#hidden_fields ⇒ Object
List of hidden fields.
352 353 354 |
# File 'lib/bureaucrat/forms.rb', line 352 def hidden_fields @fields.select {|f| f.hidden?} end |
#label_attributes(name, field) ⇒ Object
Attributes for labels, override in subclasses to customize behaviour
362 363 364 |
# File 'lib/bureaucrat/forms.rb', line 362 def label_attributes(name, field) {} end |
#multipart? ⇒ Boolean
true if this form contains fields that require the form to be multipart
347 348 349 |
# File 'lib/bureaucrat/forms.rb', line 347 def multipart? @fields.any? {|f| f..multipart_form?} end |
#non_field_errors ⇒ Object
Returns the list of errors that aren’t associated to a specific field
263 264 265 |
# File 'lib/bureaucrat/forms.rb', line 263 def non_field_errors errors.fetch(:__NON_FIELD_ERRORS, @error_class.new) end |
#populate_object(object) ⇒ Object
Populates the passed object’s attributes with data from the fields
367 368 369 370 371 |
# File 'lib/bureaucrat/forms.rb', line 367 def populate_object(object) @fields.each do |name, field| field.populate_object(object, name, @cleaned_data[name]) end end |
#valid? ⇒ Boolean
Perform validation and returns true if there are no errors
243 244 245 |
# File 'lib/bureaucrat/forms.rb', line 243 def valid? @is_bound && (errors.nil? || errors.empty?) end |
#visible_fields ⇒ Object
List of visible fields
357 358 359 |
# File 'lib/bureaucrat/forms.rb', line 357 def visible_fields @fields.select {|f| !f.hidden?} end |