Class: InlineForms::AttributeList

Inherits:
Array
  • Object
show all
Defined in:
lib/inline_forms/attribute_list.rb

Overview

A structured, mutable view over a model's inline_forms_attribute_list.

The list has always been (and remains) an Array of positional rows:

[ :name,      :text_field ]
[ :priority,  :dropdown_with_values, { 1 => 'low', 2 => 'high' } ]
[ :priority2, :dropdown_with_values, { 1 => 'low', 2 => 'high' }, [ 2 ] ]

where index 0 is the attribute, index 1 the form element, index 2 an optional values hash, and index 3 an optional disabled-options array.

Every downstream consumer relies on that shape: the views destructure |attribute, form_element|, and the helpers/validator fetch the values hash positionally with list.assoc(attr)[2]. AttributeList therefore subclasses Array and keeps rows as plain arrays — so an AttributeList IS a valid attribute list everywhere the old literal array was, with zero migration. What it adds is a small DSL/API for building and editing the list procedurally (append / insert / remove / move / replace) instead of hand-editing an array literal or regex-surgery on model source.

Build fresh:

InlineForms::AttributeList.build do
header :basics
field  :name,     :text_field
field  :priority, :dropdown_with_values, values: { 1 => 'low', 2 => 'high' }
info   :created_at, :updated_at
end

Wrap and edit an existing list (what generators / the staging pipeline do):

InlineForms::AttributeList.wrap(model.inline_forms_attribute_list)
.insert_after(:name, :internal_note, :text_field)
.remove(:legacy_field)

Mutating methods return self, so calls chain.

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.build(&block) ⇒ Object

Build a list from a block evaluated in the list's context.



42
43
44
45
46
# File 'lib/inline_forms/attribute_list.rb', line 42

def self.build(&block)
  list = new
  list.instance_eval(&block) if block
  list
end

.wrap(rows) ⇒ Object

Return rows as an AttributeList without copying when it already is one.



49
50
51
52
53
# File 'lib/inline_forms/attribute_list.rb', line 49

def self.wrap(rows)
  return rows if rows.is_a?(self)

  new(rows || [])
end

Instance Method Details

#field(name, form_element, values: nil, disabled: nil) ⇒ Object Also known as: add

Append a row. values becomes index 2, disabled index 3 (disabled requires values, since the slot is positional).



59
60
61
62
# File 'lib/inline_forms/attribute_list.rb', line 59

def field(name, form_element, values: nil, disabled: nil)
  push(build_row(name, form_element, values, disabled))
  self
end

#form_element_for(name) ⇒ Object

The form element symbol for name, or nil.



134
135
136
137
# File 'lib/inline_forms/attribute_list.rb', line 134

def form_element_for(name)
  row = row_for(name)
  row && row[1]
end

#header(name) ⇒ Object

Append a :header pseudo-row (no column, no form element behavior).



66
67
68
# File 'lib/inline_forms/attribute_list.rb', line 66

def header(name)
  field(name, :header)
end

#include_attribute?(name) ⇒ Boolean

Returns:

  • (Boolean)


124
125
126
# File 'lib/inline_forms/attribute_list.rb', line 124

def include_attribute?(name)
  !index_of(name).nil?
end

#index_of(name) ⇒ Object

-- queries ----------------------------------------------------------



119
120
121
122
# File 'lib/inline_forms/attribute_list.rb', line 119

def index_of(name)
  sym = name.to_sym
  index { |row| row_name(row) == sym }
end

#info(*names) ⇒ Object

Append one or more read-only :info rows.



71
72
73
74
# File 'lib/inline_forms/attribute_list.rb', line 71

def info(*names)
  names.each { |n| field(n, :info) }
  self
end

#insert_after(anchor, name, form_element, values: nil, disabled: nil) ⇒ Object

-- insertion --------------------------------------------------------



78
79
80
# File 'lib/inline_forms/attribute_list.rb', line 78

def insert_after(anchor, name, form_element, values: nil, disabled: nil)
  insert_relative(anchor, 1, build_row(name, form_element, values, disabled))
end

#insert_before(anchor, name, form_element, values: nil, disabled: nil) ⇒ Object



82
83
84
# File 'lib/inline_forms/attribute_list.rb', line 82

def insert_before(anchor, name, form_element, values: nil, disabled: nil)
  insert_relative(anchor, 0, build_row(name, form_element, values, disabled))
end

#move_after(name, anchor) ⇒ Object

-- reordering -------------------------------------------------------



97
98
99
# File 'lib/inline_forms/attribute_list.rb', line 97

def move_after(name, anchor)
  relocate(name, anchor, 1)
end

#move_before(name, anchor) ⇒ Object



101
102
103
# File 'lib/inline_forms/attribute_list.rb', line 101

def move_before(name, anchor)
  relocate(name, anchor, 0)
end

#namesObject



145
146
147
# File 'lib/inline_forms/attribute_list.rb', line 145

def names
  map { |row| row_name(row) }
end

#remove(name) ⇒ Object

Remove every row for name. Idempotent: absent name is a no-op.



89
90
91
92
93
# File 'lib/inline_forms/attribute_list.rb', line 89

def remove(name)
  sym = name.to_sym
  reject! { |row| row_name(row) == sym }
  self
end

#replace_element(name, form_element, values: nil, disabled: nil) ⇒ Object

Swap the form element (and optional values/disabled) for an existing attribute, preserving its position. No-op if the attribute is absent.



109
110
111
112
113
114
115
# File 'lib/inline_forms/attribute_list.rb', line 109

def replace_element(name, form_element, values: nil, disabled: nil)
  idx = index_of(name)
  return self unless idx

  self[idx] = build_row(name, form_element, values, disabled)
  self
end

#row_for(name) ⇒ Object



128
129
130
131
# File 'lib/inline_forms/attribute_list.rb', line 128

def row_for(name)
  sym = name.to_sym
  find { |row| row_name(row) == sym }
end

#values_for(name) ⇒ Object

The values hash for name (row index 2), or nil.



140
141
142
143
# File 'lib/inline_forms/attribute_list.rb', line 140

def values_for(name)
  row = row_for(name)
  row && row[2]
end