module Formality::ClassMethods
Attributes
¶ ↑
Working with models
¶ ↑
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.
Public Instance Methods
A convenience class method for creating and assigning a Hash to a form.
# File lib/formality.rb, line 77 def assign(attrs) new.assign(attrs) end
Declare an attribute.
Defines a reader and writer. Accepts a :default options for the default value of the attribute.
# File lib/formality.rb, line 64 def attribute(name, options={}) attributes << name.to_s define_reader(name, options[:default]) attr_writer name end
A Set of attribute names, stored on the form class.
# File lib/formality.rb, line 71 def attributes @__attributes ||= Set.new end
Build a form object from an existing model.
If nested forms were declared with the :from_model_attribute option, it will also build the nested form object(s).
# File lib/formality.rb, line 147 def from_model(model) new.tap do |form| form.id = model.id form.assign(model.attributes) nested_forms.each do |nested| form.send("#{nested}=", model) end end end
Declare the model that this form object represents.
Purely a convenience so that you don’t have to specify the :url parameter in your :form_for calls.
# File lib/formality.rb, line 137 def model(name_sym) model_klass = name_sym.to_s.capitalize.constantize @__model_name = ActiveModel::Name.new(model_klass) end
:model_name must be defined on the class and return a String with various convenience methods. ActiveModel::Name gives us that.
By default, :model_name uses the name of the Form class.
# File lib/formality.rb, line 27 def model_name @__model_name ||= ActiveModel::Name.new(self) end
Plural nesting.
Works just like :nest_one, except it works for an Array of nested forms.
# File lib/formality.rb, line 207 def nest_many(children, options={}) add_nested_form(children) define_nested_form_many(children, options) end
Singular Nesting.
# File lib/formality.rb, line 198 def nest_one(child, options={}) add_nested_form(child) define_nested_form_one(child, options) end
Keep track of what forms we’ve nested.
# File lib/formality.rb, line 213 def nested_forms @__nested_forms ||= Set.new end
Private Instance Methods
# File lib/formality.rb, line 219 def add_nested_form(nested) attributes << "#{nested}_attributes" nested_forms << nested end
Define the accessors for a plural nested form.
# File lib/formality.rb, line 247 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
Define the accessors for a singular nested form.
# File lib/formality.rb, line 225 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
Defines an attribute reader with an optional default value.
# File lib/formality.rb, line 85 def define_reader(name, default=nil) class_eval <<-reader def #{name} @#{name} ||= #{default.inspect} end reader end