module Formality
Constants
- VERSION
Attributes
Public Instance Methods
Assigns a hash of attributes to the form. Only assigns values if the key for that value is a declared attribute. It silently ignores non-declared keys.
# File lib/formality.rb, line 112 def assign(new_attributes) new_attributes.each do |name, value| next unless attribute?(name) send("#{name}=", value) end self.id = new_attributes[:id] self end
Returns a Boolean that answers the question: Is this ‘name` a declared attribute?
# File lib/formality.rb, line 123 def attribute?(name) attribute_names.include?(name.to_s) end
Returns an Array of attribute names (Strings).
# File lib/formality.rb, line 95 def attribute_names self.class.attributes.to_a end
Returns a HashWithIndifferentAccess of all the defined attributes and their values.
# File lib/formality.rb, line 101 def attributes hash = ActiveSupport::HashWithIndifferentAccess.new attribute_names.each_with_object({}) do |name| hash[name] = send(name) end hash end
Same as :valid, but in reverse: only yields to the block if the form is invalid.
# File lib/formality.rb, line 183 def invalid; yield if invalid? end # # Nesting # ======= # # Allows forms to have forms nested within them that # work nicely with Rails' :fields_for method. # # Validations are called on nested forms, so that if # any nested form is invalid, so is the parent. # module ClassMethods # Singular Nesting. def nest_one(child, options={}) add_nested_form(child) define_nested_form_one(child, options) end # Plural nesting. # # Works just like :nest_one, except it works for # an Array of nested forms. def nest_many(children, options={}) add_nested_form(children) define_nested_form_many(children, options) end # Keep track of what forms we've nested. def nested_forms @__nested_forms ||= Set.new end private def add_nested_form(nested) attributes << "#{nested}_attributes" nested_forms << nested end # Define the accessors for a singular nested form. def define_nested_form_one(name, options={}) define_reader(name) from_model_attribute = options[:from_model_attribute] class_eval <<-one def #{name}_attributes self.#{name} ? @#{name}.attributes : nil end def #{name}_attributes=(attrs) form_klass = "#{name}".classify.constantize @#{name} = form_klass.new.assign(attrs) end def #{name}=(model) return unless #{from_model_attribute.inspect} nested_model = model.send(#{from_model_attribute.inspect}) self.#{name}_attributes = nested_model.attributes end one end # Define the accessors for a plural nested form. def define_nested_form_many(name, options={}) define_reader(name, []) from_model_attribute = options[:from_model_attribute] class_eval <<-many def #{name}_attributes self.#{name}.map { |form| form.attributes } end def #{name}_attributes=(attrs_array) form_klass = "#{name}".classify.constantize @#{name} = attrs_array.map do |attrs| form_klass.new.assign(attrs) end end def #{name}=(model) return unless #{from_model_attribute.inspect} nested_models = model.send(#{from_model_attribute.inspect}) self.#{name}_attributes = nested_models.map { |m| m.attributes } end many end end # A Formality form object is valid if its attributes # validate and all of its children are valid. def valid?(context=nil) nested_forms_valid?(context) && super(context) end # If there are nested forms, call :valid? on them. def nested_forms_valid?(context) self.class.nested_forms.all? do |name| nested = Array(send(name)) nested.all? { |form| form.valid?(context) } end end end
If there are nested forms, call :valid? on them.
# File lib/formality.rb, line 278 def nested_forms_valid?(context) self.class.nested_forms.all? do |name| nested = Array(send(name)) nested.all? { |form| form.valid?(context) } end end
:form_for calls :persisted? on the object it receives to determine whether to :post or :put.
We assume we’re persisted (i.e. editing an object) if we have an id.
# File lib/formality.rb, line 50 def persisted? id.present? end
More ActiveModel compliance shenanigans.
# File lib/formality.rb, line 33 def to_key; end
# File lib/formality.rb, line 34 def to_param; end
# File lib/formality.rb, line 35 def to_partial_path; "" end
Yields to its block if the form is valid.
# File lib/formality.rb, line 179 def valid; yield if valid? end # Same as :valid, but in reverse: only yields to # the block if the form is invalid. def invalid; yield if invalid? end # # Nesting # ======= # # Allows forms to have forms nested within them that # work nicely with Rails' :fields_for method. # # Validations are called on nested forms, so that if # any nested form is invalid, so is the parent. # module ClassMethods # Singular Nesting. def nest_one(child, options={}) add_nested_form(child) define_nested_form_one(child, options) end # Plural nesting. # # Works just like :nest_one, except it works for # an Array of nested forms. def nest_many(children, options={}) add_nested_form(children) define_nested_form_many(children, options) end # Keep track of what forms we've nested. def nested_forms @__nested_forms ||= Set.new end private def add_nested_form(nested) attributes << "#{nested}_attributes" nested_forms << nested end # Define the accessors for a singular nested form. def define_nested_form_one(name, options={}) define_reader(name) from_model_attribute = options[:from_model_attribute] class_eval <<-one def #{name}_attributes self.#{name} ? @#{name}.attributes : nil end def #{name}_attributes=(attrs) form_klass = "#{name}".classify.constantize @#{name} = form_klass.new.assign(attrs) end def #{name}=(model) return unless #{from_model_attribute.inspect} nested_model = model.send(#{from_model_attribute.inspect}) self.#{name}_attributes = nested_model.attributes end one end # Define the accessors for a plural nested form. def define_nested_form_many(name, options={}) define_reader(name, []) from_model_attribute = options[:from_model_attribute] class_eval <<-many def #{name}_attributes self.#{name}.map { |form| form.attributes } end def #{name}_attributes=(attrs_array) form_klass = "#{name}".classify.constantize @#{name} = attrs_array.map do |attrs| form_klass.new.assign(attrs) end end def #{name}=(model) return unless #{from_model_attribute.inspect} nested_models = model.send(#{from_model_attribute.inspect}) self.#{name}_attributes = nested_models.map { |m| m.attributes } end many end end # A Formality form object is valid if its attributes # validate and all of its children are valid. def valid?(context=nil) nested_forms_valid?(context) && super(context) end # If there are nested forms, call :valid? on them. def nested_forms_valid?(context) self.class.nested_forms.all? do |name| nested = Array(send(name)) nested.all? { |form| form.valid?(context) } end end
A Formality
form object is valid if its attributes validate and all of its children are valid.
# File lib/formality.rb, line 273 def valid?(context=nil) nested_forms_valid?(context) && super(context) end