Class: Protoform::Namespace

Inherits:
Node
  • Object
show all
Includes:
Enumerable
Defined in:
lib/protoform/namespace.rb

Overview

A Namespace maps and object to values, but doesn't actually have a value itself. For example, a User object or ActiveRecord model could be passed into the :user namespace. To access the values on a Namespace, the field can be called for single values.

Additionally, to access namespaces within a namespace, such as if a User has_many :addresses in ActiveRecord, the namespace method can be called which will return another Namespace object and set the current Namespace as the parent.

Instance Attribute Summary collapse

Attributes inherited from Node

#key, #parent

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(key, parent:, object: nil, field_class: Field) {|_self| ... } ⇒ Namespace

Returns a new instance of Namespace.

Yields:

  • (_self)

Yield Parameters:



18
19
20
21
22
23
24
# File 'lib/protoform/namespace.rb', line 18

def initialize(key, parent:, object: nil, field_class: Field)
  super(key, parent:)
  @object = object
  @field_class = field_class
  @children = {}
  yield self if block_given?
end

Instance Attribute Details

#object ⇒ Object (readonly)

Returns the value of attribute object.



16
17
18
# File 'lib/protoform/namespace.rb', line 16

def object
  @object
end

Class Method Details

.root ⇒ Object

Creates a root Namespace, which is essentially a form.



123
124
125
# File 'lib/protoform/namespace.rb', line 123

def self.root(*, **, &)
  new(*, parent: nil, **, &)
end

Instance Method Details

#assign(hash) ⇒ Object

Assigns a hash to the current namespace and children namespace.



114
115
116
117
118
119
120
# File 'lib/protoform/namespace.rb', line 114

def assign(hash)
  tap do
    each do |child|
      child.assign hash[child.key] if hash.key? child.key
    end
  end
end

#collection(key) ⇒ Object

Wraps an array of objects in Namespace classes. For example, if User#addresses returns an enumerable or array of Address classes:

Protoform :user, object: User.new do |form|
  form.field :email
  form.field :name
  form.collection :addresses do |address|
    address.field(:street)
    address.field(:state)
    address.field(:zip)
  end
end

The object within the block is a Namespace object that maps each object within the enumerable to another Namespace or Field.



87
88
89
90
91
92
93
94
# File 'lib/protoform/namespace.rb', line 87

def collection(key, &)
  create_child(
    key:,
    child_class: NamespaceCollection,
    field_class: @field_class,
    &
  )
end

#each ⇒ Object

Iterates through the children of the current namespace, which could be Namespace or Field objects.



109
110
111
# File 'lib/protoform/namespace.rb', line 109

def each(&)
  @children.values.each(&)
end

#field(key) ⇒ Object

Maps the Object#proprety and Object#property= to a field in a web form that can be read and set by the form. For example, a User form might look like this:

Protoform :user, object: User.new do |form|
  form.field :email
  form.field :name
end


61
62
63
64
65
66
67
68
69
# File 'lib/protoform/namespace.rb', line 61

def field(key)
  create_child(
    key:,
    child_class: @field_class,
    object:
  ).tap do |field|
    yield field if block_given?
  end
end

#namespace(key) ⇒ Object

Creates a Namespace child instance with the parent set to the current instance, adds to the @children Hash to ensure duplicate child namespaces aren't created, then calls the method on the @object to get the child object to pass into that namespace.

For example, if a User#permission returns a Permission object, we could map that to a form like this:

Protoform :user, object: User.new do |form|
  form.namespace :permission do |permission|
    form.field :role
  end
end


41
42
43
44
45
46
47
48
49
# File 'lib/protoform/namespace.rb', line 41

def namespace(key, &)
  create_child(
    key:,
    child_class: self.class,
    field_class: @field_class,
    object: object_for(key:),
    &
  )
end

#serialize ⇒ Object

Creates a Hash of Hashes and Arrays that represent the fields and collections of the Protoform. This can be used to safely update ActiveRecord objects without the need for Strong Parameters. You will want to make sure that all the fields displayed in the form are ones that you're OK updating from the generated hash.



101
102
103
104
105
# File 'lib/protoform/namespace.rb', line 101

def serialize
  each_with_object({}) do |child, hash|
    hash[child.key] = child.serialize
  end
end