compony 0.11.8 → 0.11.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (132) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +36 -1
  3. data/CHANGELOG.md +31 -0
  4. data/CLAUDE.md +85 -0
  5. data/Gemfile.lock +1 -1
  6. data/README.md +13 -3
  7. data/VERSION +1 -1
  8. data/compony.gemspec +3 -3
  9. data/doc/ComponentGenerator.html +1 -1
  10. data/doc/Components.html +1 -1
  11. data/doc/ComponentsGenerator.html +1 -1
  12. data/doc/Compony/Component.html +54 -54
  13. data/doc/Compony/ComponentMixins/Default/Labelling.html +1 -1
  14. data/doc/Compony/ComponentMixins/Default/Standalone/ResourcefulVerbDsl.html +1 -1
  15. data/doc/Compony/ComponentMixins/Default/Standalone/StandaloneDsl.html +109 -70
  16. data/doc/Compony/ComponentMixins/Default/Standalone/VerbDsl.html +64 -28
  17. data/doc/Compony/ComponentMixins/Default/Standalone.html +1 -1
  18. data/doc/Compony/ComponentMixins/Default.html +1 -1
  19. data/doc/Compony/ComponentMixins/Resourceful.html +213 -74
  20. data/doc/Compony/ComponentMixins.html +1 -1
  21. data/doc/Compony/Components/Buttons/CssButton.html +1 -1
  22. data/doc/Compony/Components/Buttons/Link.html +1 -1
  23. data/doc/Compony/Components/Buttons.html +1 -1
  24. data/doc/Compony/Components/Destroy.html +83 -29
  25. data/doc/Compony/Components/Edit.html +110 -38
  26. data/doc/Compony/Components/Form.html +551 -208
  27. data/doc/Compony/Components/Index.html +1 -1
  28. data/doc/Compony/Components/List.html +3 -3
  29. data/doc/Compony/Components/New.html +110 -38
  30. data/doc/Compony/Components/Show.html +1 -1
  31. data/doc/Compony/Components/WithForm.html +194 -47
  32. data/doc/Compony/Components.html +1 -1
  33. data/doc/Compony/ControllerMixin.html +1 -1
  34. data/doc/Compony/Engine.html +1 -1
  35. data/doc/Compony/Intent.html +2 -2
  36. data/doc/Compony/ManageIntentsDsl.html +1 -1
  37. data/doc/Compony/MethodAccessibleHash.html +1 -1
  38. data/doc/Compony/ModelFields/Anchormodel.html +1 -1
  39. data/doc/Compony/ModelFields/Association.html +1 -1
  40. data/doc/Compony/ModelFields/Attachment.html +1 -1
  41. data/doc/Compony/ModelFields/Base.html +1 -1
  42. data/doc/Compony/ModelFields/Boolean.html +1 -1
  43. data/doc/Compony/ModelFields/Color.html +1 -1
  44. data/doc/Compony/ModelFields/Currency.html +1 -1
  45. data/doc/Compony/ModelFields/Date.html +1 -1
  46. data/doc/Compony/ModelFields/Datetime.html +1 -1
  47. data/doc/Compony/ModelFields/Decimal.html +1 -1
  48. data/doc/Compony/ModelFields/Email.html +1 -1
  49. data/doc/Compony/ModelFields/Float.html +1 -1
  50. data/doc/Compony/ModelFields/Integer.html +1 -1
  51. data/doc/Compony/ModelFields/Percentage.html +1 -1
  52. data/doc/Compony/ModelFields/Phone.html +1 -1
  53. data/doc/Compony/ModelFields/RichText.html +1 -1
  54. data/doc/Compony/ModelFields/String.html +1 -1
  55. data/doc/Compony/ModelFields/Text.html +1 -1
  56. data/doc/Compony/ModelFields/Time.html +1 -1
  57. data/doc/Compony/ModelFields/Url.html +1 -1
  58. data/doc/Compony/ModelFields.html +1 -1
  59. data/doc/Compony/ModelMixin.html +1 -1
  60. data/doc/Compony/NaturalOrdering.html +1 -1
  61. data/doc/Compony/RequestContext.html +1 -1
  62. data/doc/Compony/Version.html +1 -1
  63. data/doc/Compony/ViewHelpers.html +1 -1
  64. data/doc/Compony/VirtualModel.html +1 -1
  65. data/doc/Compony.html +1 -1
  66. data/doc/ComponyController.html +1 -1
  67. data/doc/_index.html +97 -1
  68. data/doc/file.CHANGELOG.html +758 -0
  69. data/doc/file.README.html +25 -4
  70. data/doc/file.basic_component.html +314 -0
  71. data/doc/file.cookbook.html +189 -0
  72. data/doc/file.destroy.html +105 -0
  73. data/doc/file.dsl_reference.html +672 -0
  74. data/doc/file.edit.html +109 -0
  75. data/doc/file.example.html +291 -0
  76. data/doc/file.example_advanced.html +257 -0
  77. data/doc/file.feasibility.html +115 -0
  78. data/doc/file.form.html +195 -0
  79. data/doc/file.generators.html +89 -0
  80. data/doc/file.glossary.html +217 -0
  81. data/doc/file.gotchas.html +222 -0
  82. data/doc/file.index.html +135 -0
  83. data/doc/file.inheritance.html +136 -0
  84. data/doc/file.installation.html +115 -0
  85. data/doc/file.integrations.html +218 -0
  86. data/doc/file.intents.html +265 -0
  87. data/doc/file.internal_datastructures.html +129 -0
  88. data/doc/file.list.html +253 -0
  89. data/doc/file.maintaining.html +127 -0
  90. data/doc/file.model_fields.html +137 -0
  91. data/doc/file.nesting.html +237 -0
  92. data/doc/file.new.html +109 -0
  93. data/doc/file.ownership.html +98 -0
  94. data/doc/file.patterns.html +669 -0
  95. data/doc/file.pre_built_components.html +99 -0
  96. data/doc/file.resourceful.html +181 -0
  97. data/doc/file.show.html +158 -0
  98. data/doc/file.standalone.html +233 -0
  99. data/doc/file.virtual_models.html +117 -0
  100. data/doc/file.with_form.html +157 -0
  101. data/doc/file_list.html +160 -0
  102. data/doc/guide/cookbook.md +41 -0
  103. data/doc/guide/dsl_reference.md +155 -0
  104. data/doc/guide/example_advanced.md +209 -0
  105. data/doc/guide/generators.md +1 -1
  106. data/doc/guide/glossary.md +42 -0
  107. data/doc/guide/gotchas.md +125 -0
  108. data/doc/guide/maintaining.md +64 -0
  109. data/doc/guide/patterns.md +681 -0
  110. data/doc/guide/pre_built_components/edit.md +1 -1
  111. data/doc/guide/pre_built_components/index.md +64 -1
  112. data/doc/guide/pre_built_components/list.md +111 -7
  113. data/doc/guide/pre_built_components/show.md +57 -2
  114. data/doc/guide/pre_built_components/with_form.md +56 -9
  115. data/doc/guide/pre_built_components.md +7 -2
  116. data/doc/guide/standalone.md +16 -1
  117. data/doc/index.html +25 -4
  118. data/doc/integrations.md +61 -0
  119. data/doc/llms.txt +62 -0
  120. data/doc/top-level-namespace.html +1 -1
  121. data/lib/compony/component.rb +8 -3
  122. data/lib/compony/component_mixins/default/standalone/standalone_dsl.rb +32 -15
  123. data/lib/compony/component_mixins/default/standalone/verb_dsl.rb +11 -3
  124. data/lib/compony/component_mixins/resourceful.rb +30 -16
  125. data/lib/compony/components/destroy.rb +21 -1
  126. data/lib/compony/components/edit.rb +25 -1
  127. data/lib/compony/components/form.rb +63 -21
  128. data/lib/compony/components/list.rb +1 -1
  129. data/lib/compony/components/new.rb +25 -1
  130. data/lib/compony/components/with_form.rb +20 -5
  131. data/lib/compony/intent.rb +1 -1
  132. metadata +43 -1
@@ -0,0 +1,253 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>
7
+ File: list
8
+
9
+ &mdash; Documentation by YARD 0.9.34
10
+
11
+ </title>
12
+
13
+ <link rel="stylesheet" href="css/style.css" type="text/css" />
14
+
15
+ <link rel="stylesheet" href="css/common.css" type="text/css" />
16
+
17
+ <script type="text/javascript">
18
+ pathId = "list";
19
+ relpath = '';
20
+ </script>
21
+
22
+
23
+ <script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
24
+
25
+ <script type="text/javascript" charset="utf-8" src="js/app.js"></script>
26
+
27
+
28
+ </head>
29
+ <body>
30
+ <div class="nav_wrap">
31
+ <iframe id="nav" src="file_list.html?1"></iframe>
32
+ <div id="resizer"></div>
33
+ </div>
34
+
35
+ <div id="main" tabindex="-1">
36
+ <div id="header">
37
+ <div id="menu">
38
+
39
+ <a href="_index.html">Index</a> &raquo;
40
+ <span class="title">File: list</span>
41
+
42
+ </div>
43
+
44
+ <div id="search">
45
+
46
+ <a class="full_list_link" id="class_list_link"
47
+ href="class_list.html">
48
+
49
+ <svg width="24" height="24">
50
+ <rect x="0" y="4" width="24" height="4" rx="1" ry="1"></rect>
51
+ <rect x="0" y="12" width="24" height="4" rx="1" ry="1"></rect>
52
+ <rect x="0" y="20" width="24" height="4" rx="1" ry="1"></rect>
53
+ </svg>
54
+ </a>
55
+
56
+ </div>
57
+ <div class="clear"></div>
58
+ </div>
59
+
60
+ <div id="content"><div id='filecontents'><ul><li>
61
+ <p><a href="/README_md.html#guide--documentation">Back to the guide</a></p>
62
+ </li><li>
63
+ <p><a href="/doc/guide/pre_built_components_md.html">List of pre-built components</a></p>
64
+ </li></ul>
65
+
66
+ <h1 id="label-Pre-built+components-3A+List">Pre-built components: List</h1>
67
+
68
+ <p><code>Compony::Components::List</code> is a resourceful component that renders a table/list of records. It is <strong>not</strong> standalone — it is meant to be nested, typically inside href="./index_md.html"></a> of the same family or href="./show_md.html"></a> of an owning family, via <code>render_sub_comp(:list, collection)</code>.</p>
69
+
70
+ <p>Features: field-inferred or custom columns, per-row intents, pagination, and — when the <a href="https://github.com/activerecord-hackery/ransack">Ransack</a> gem is present and at least one sort/filter is declared — sorting links, a sort select, and a filter/search form.</p>
71
+
72
+ <h2 id="label-Column+DSL">Column DSL</h2>
73
+
74
+ <table role="table">
75
+ <thead>
76
+ <tr>
77
+ <th>Method</th>
78
+ <th>Signature</th>
79
+ <th>Description</th>
80
+ </tr>
81
+ </thead>
82
+ <tbody>
83
+ <tr>
84
+ <td>‘column`</td>
85
+ <td>‘column(:name, label: nil, class: nil, link_opts: {}) { |record| … }`</td>
86
+ <td>Add/define a column. No block → model-field column (auto label, value via ‘value_for`, only if `:index` permitted). Block is instance-exec’d per row and renders the cell.</td>
87
+ </tr>
88
+ <tr>
89
+ <td>‘columns`</td>
90
+ <td>‘columns(:a, :b, as_title: false, **kw)`</td>
91
+ <td>Bulk ‘column`. `as_title: true` marks title columns (shown as the card heading in mobile/card layouts).</td>
92
+ </tr>
93
+ <tr>
94
+ <td>‘skip_column`</td>
95
+ <td>‘skip_column(:name)`</td>
96
+ <td>Hide a (possibly inherited) column.</td>
97
+ </tr>
98
+ </tbody>
99
+ </table>
100
+
101
+ <pre class="code ruby"><code class="ruby"><span class='kw'>class</span> <span class='const'><span class='object_link'><a href="Components.html" title="Components (module)">Components</a></span></span><span class='op'>::</span><span class='const'>Orders</span><span class='op'>::</span><span class='const'>List</span> <span class='op'>&lt;</span> <span class='const'><span class='object_link'><a href="Compony.html" title="Compony (module)">Compony</a></span></span><span class='op'>::</span><span class='const'><span class='object_link'><a href="Compony/Components.html" title="Compony::Components (module)">Components</a></span></span><span class='op'>::</span><span class='const'><span class='object_link'><a href="Compony/Components/List.html" title="Compony::Components::List (class)">List</a></span></span>
102
+ <span class='id identifier rubyid_setup'>setup</span> <span class='kw'>do</span>
103
+ <span class='id identifier rubyid_columns'>columns</span> <span class='symbol'>:number</span><span class='comma'>,</span> <span class='symbol'>:customer</span><span class='comma'>,</span> <span class='label'>as_title:</span> <span class='kw'>true</span>
104
+ <span class='id identifier rubyid_columns'>columns</span> <span class='symbol'>:total</span><span class='comma'>,</span> <span class='symbol'>:created_at</span>
105
+ <span class='id identifier rubyid_column'>column</span> <span class='symbol'>:status</span><span class='comma'>,</span> <span class='label'>class:</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>text-end</span><span class='tstring_end'>&#39;</span></span> <span class='kw'>do</span> <span class='op'>|</span><span class='id identifier rubyid_order'>order</span><span class='op'>|</span>
106
+ <span class='id identifier rubyid_span'>span</span> <span class='id identifier rubyid_order'>order</span><span class='period'>.</span><span class='id identifier rubyid_status'>status</span><span class='period'>.</span><span class='id identifier rubyid_label'>label</span><span class='comma'>,</span> <span class='label'>class:</span> <span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>badge bg-</span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_order'>order</span><span class='period'>.</span><span class='id identifier rubyid_status'>status</span><span class='period'>.</span><span class='id identifier rubyid_key'>key</span><span class='embexpr_end'>}</span><span class='tstring_end'>&quot;</span></span>
107
+ <span class='kw'>end</span>
108
+ <span class='kw'>end</span>
109
+ <span class='kw'>end</span>
110
+ </code></pre>
111
+
112
+ <h2 id="label-Filtering+-26+sorting+-28Ransack-29">Filtering &amp; sorting (Ransack)</h2>
113
+
114
+ <table role="table">
115
+ <thead>
116
+ <tr>
117
+ <th>Method</th>
118
+ <th>Signature</th>
119
+ <th>Description</th>
120
+ </tr>
121
+ </thead>
122
+ <tbody>
123
+ <tr>
124
+ <td>‘filter`</td>
125
+ <td>‘filter(:name, label: nil) { |f| … }`</td>
126
+ <td>Add a filter. No block → field filter or a Ransack predicate string (e.g. ‘:id_eq`). Block gets the Ransack search form and renders label + input.</td>
127
+ </tr>
128
+ <tr>
129
+ <td>‘filters`</td>
130
+ <td>‘filters(:a, :b, **kw)`</td>
131
+ <td>Bulk ‘filter`.</td>
132
+ </tr>
133
+ <tr>
134
+ <td>‘sort`</td>
135
+ <td>‘sort(:name, label: nil)`</td>
136
+ <td>Add a sort criterion (must be Ransack-sortable). Generates one sort link + asc/desc entries.</td>
137
+ </tr>
138
+ <tr>
139
+ <td>‘sorts`</td>
140
+ <td>‘sorts(:a, :b)`</td>
141
+ <td>Bulk ‘sort`.</td>
142
+ </tr>
143
+ <tr>
144
+ <td>‘default_sorting`</td>
145
+ <td>‘default_sorting(’id desc’)‘</td>
146
+ <td>Default Ransack sort applied when none chosen.</td>
147
+ </tr>
148
+ </tbody>
149
+ </table>
150
+
151
+ <pre class="code ruby"><code class="ruby"><span class='id identifier rubyid_setup'>setup</span> <span class='kw'>do</span>
152
+ <span class='id identifier rubyid_filters'>filters</span> <span class='symbol'>:number</span><span class='comma'>,</span> <span class='symbol'>:status</span>
153
+ <span class='id identifier rubyid_filter'>filter</span> <span class='symbol'>:overdue</span><span class='comma'>,</span> <span class='label'>label:</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>Overdue</span><span class='tstring_end'>&#39;</span></span> <span class='kw'>do</span> <span class='op'>|</span><span class='id identifier rubyid_f'>f</span><span class='op'>|</span>
154
+ <span class='id identifier rubyid_concat'>concat</span> <span class='id identifier rubyid_f'>f</span><span class='period'>.</span><span class='id identifier rubyid_check_box'>check_box</span><span class='lparen'>(</span><span class='symbol'>:overdue_eq</span><span class='comma'>,</span> <span class='lbrace'>{</span><span class='rbrace'>}</span><span class='comma'>,</span> <span class='kw'>true</span><span class='comma'>,</span> <span class='kw'>false</span><span class='rparen'>)</span>
155
+ <span class='kw'>end</span>
156
+ <span class='id identifier rubyid_sorts'>sorts</span> <span class='symbol'>:number</span><span class='comma'>,</span> <span class='symbol'>:created_at</span>
157
+ <span class='id identifier rubyid_default_sorting'>default_sorting</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>created_at desc</span><span class='tstring_end'>&#39;</span></span>
158
+ <span class='kw'>end</span>
159
+ </code></pre>
160
+
161
+ <h2 id="label-Per-row+intents">Per-row intents</h2>
162
+
163
+ <p><code>row_intents</code> opens the <a href="/doc/guide/intents_md.html#exposed-intents">intent management DSL</a> (<code>add</code>/<code>remove</code>, <code>before:</code>) applied to each row’s record:</p>
164
+
165
+ <pre class="code ruby"><code class="ruby"><span class='id identifier rubyid_setup'>setup</span> <span class='kw'>do</span>
166
+ <span class='id identifier rubyid_row_intents'>row_intents</span> <span class='kw'>do</span>
167
+ <span class='id identifier rubyid_remove'>remove</span> <span class='symbol'>:destroy</span>
168
+ <span class='id identifier rubyid_add'>add</span> <span class='symbol'>:archive</span><span class='comma'>,</span> <span class='tlambda'>-&gt;</span><span class='lparen'>(</span><span class='id identifier rubyid_record'>record</span><span class='rparen'>)</span> <span class='tlambeg'>{</span> <span class='id identifier rubyid_record'>record</span> <span class='rbrace'>}</span><span class='comma'>,</span> <span class='label'>method:</span> <span class='symbol'>:patch</span><span class='comma'>,</span> <span class='label'>before:</span> <span class='symbol'>:edit</span>
169
+ <span class='kw'>end</span>
170
+ <span class='kw'>end</span>
171
+ </code></pre>
172
+
173
+ <h2 id="label-Toggles-2C+paging-2C+styling">Toggles, paging, styling</h2>
174
+
175
+ <p>All have matching constructor kwargs so a nesting parent can override per render (<code>render_sub_comp(:list, coll, skip_pagination: true, skip_columns: [:order])</code>).</p>
176
+
177
+ <table role="table">
178
+ <thead>
179
+ <tr>
180
+ <th>DSL</th>
181
+ <th>Default</th>
182
+ <th>Purpose</th>
183
+ </tr>
184
+ </thead>
185
+ <tbody>
186
+ <tr>
187
+ <td>‘pagination(bool)`</td>
188
+ <td>on</td>
189
+ <td>Enable/disable paging (off loads all rows).</td>
190
+ </tr>
191
+ <tr>
192
+ <td>‘results_per_page(n)`</td>
193
+ <td>20</td>
194
+ <td>Rows per page.</td>
195
+ </tr>
196
+ <tr>
197
+ <td>‘filtering(bool)`</td>
198
+ <td>on</td>
199
+ <td>Enable/disable the filter form.</td>
200
+ </tr>
201
+ <tr>
202
+ <td>‘sorting(bool)` / `sorting_in_filter(bool)` / `sorting_links(bool)`</td>
203
+ <td>on</td>
204
+ <td>Toggle sort UIs.</td>
205
+ </tr>
206
+ <tr>
207
+ <td>‘filter_label_class` / `filter_input_class` / `filter_select_class` / `filter_item_wrapper_class`</td>
208
+ <td>—</td>
209
+ <td>CSS classes for filter form elements.</td>
210
+ </tr>
211
+ </tbody>
212
+ </table>
213
+
214
+ <p>Constructor <code>skip_*</code> kwargs: <code>skip_pagination</code>, <code>skip_filtering</code>, <code>skip_sorting</code>, <code>skip_sorting_in_filter</code>, <code>skip_sorting_links</code>, <code>skip_columns:</code>, <code>skip_row_intents:</code>, <code>skip_filters:</code>, <code>results_per_page:</code>, <code>default_sorting:</code>.</p>
215
+
216
+ <h2 id="label-Customizing+rendering">Customizing rendering</h2>
217
+
218
+ <p><code>List</code> exposes named <code>content</code> blocks (<code>:data</code>, <code>:filter</code>, <code>:pagination</code>, <code>:sorting_links</code>, …) that you override — almost always once, in an app <code>BaseComponents::List</code>, to fit your UI framework, then inherited everywhere:</p>
219
+
220
+ <pre class="code ruby"><code class="ruby"><span class='kw'>module</span> <span class='const'>BaseComponents</span>
221
+ <span class='kw'>class</span> <span class='const'>List</span> <span class='op'>&lt;</span> <span class='const'><span class='object_link'><a href="Compony.html" title="Compony (module)">Compony</a></span></span><span class='op'>::</span><span class='const'><span class='object_link'><a href="Compony/Components.html" title="Compony::Components (module)">Components</a></span></span><span class='op'>::</span><span class='const'><span class='object_link'><a href="Compony/Components/List.html" title="Compony::Components::List (class)">List</a></span></span>
222
+ <span class='id identifier rubyid_setup'>setup</span> <span class='kw'>do</span>
223
+ <span class='id identifier rubyid_filter_input_class'>filter_input_class</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>form-control</span><span class='tstring_end'>&#39;</span></span>
224
+ <span class='id identifier rubyid_content'>content</span> <span class='symbol'>:filter</span><span class='comma'>,</span> <span class='label'>hidden:</span> <span class='kw'>true</span> <span class='kw'>do</span>
225
+ <span class='comment'># Bootstrap-styled filter form wrapper
226
+ </span> <span class='kw'>end</span>
227
+ <span class='id identifier rubyid_content'>content</span> <span class='symbol'>:data</span><span class='comma'>,</span> <span class='label'>hidden:</span> <span class='kw'>true</span> <span class='kw'>do</span>
228
+ <span class='comment'># Bootstrap table / responsive cards
229
+ </span> <span class='kw'>end</span>
230
+ <span class='kw'>end</span>
231
+ <span class='kw'>end</span>
232
+ <span class='kw'>end</span>
233
+ </code></pre>
234
+
235
+ <p>Embedding a child list inside a Show, dropping the FK column and preserving the active tab across filter submits:</p>
236
+
237
+ <pre class="code ruby"><code class="ruby"><span class='id identifier rubyid_concat'>concat</span> <span class='id identifier rubyid_render_sub_comp'>render_sub_comp</span><span class='lparen'>(</span><span class='symbol'>:list</span><span class='comma'>,</span> <span class='ivar'>@data</span><span class='period'>.</span><span class='id identifier rubyid_line_items'>line_items</span><span class='comma'>,</span>
238
+ <span class='label'>skip_columns:</span> <span class='lbracket'>[</span><span class='symbol'>:order</span><span class='rbracket'>]</span><span class='comma'>,</span>
239
+ <span class='label'>params_in_filter:</span> <span class='lbracket'>[</span><span class='id identifier rubyid_param_name'>param_name</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>tab</span><span class='tstring_end'>&#39;</span></span><span class='rparen'>)</span><span class='rbracket'>]</span><span class='rparen'>)</span>
240
+ </code></pre>
241
+
242
+ <p>See <a href="../patterns_md.html#4-list-customization">Real-world patterns</a> for the recurring app setup.</p>
243
+ </div></div>
244
+
245
+ <div id="footer">
246
+ Generated on Mon May 18 13:55:33 2026 by
247
+ <a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
248
+ 0.9.34 (ruby-3.3.5).
249
+ </div>
250
+
251
+ </div>
252
+ </body>
253
+ </html>
@@ -0,0 +1,127 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>
7
+ File: maintaining
8
+
9
+ &mdash; Documentation by YARD 0.9.34
10
+
11
+ </title>
12
+
13
+ <link rel="stylesheet" href="css/style.css" type="text/css" />
14
+
15
+ <link rel="stylesheet" href="css/common.css" type="text/css" />
16
+
17
+ <script type="text/javascript">
18
+ pathId = "maintaining";
19
+ relpath = '';
20
+ </script>
21
+
22
+
23
+ <script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
24
+
25
+ <script type="text/javascript" charset="utf-8" src="js/app.js"></script>
26
+
27
+
28
+ </head>
29
+ <body>
30
+ <div class="nav_wrap">
31
+ <iframe id="nav" src="file_list.html?1"></iframe>
32
+ <div id="resizer"></div>
33
+ </div>
34
+
35
+ <div id="main" tabindex="-1">
36
+ <div id="header">
37
+ <div id="menu">
38
+
39
+ <a href="_index.html">Index</a> &raquo;
40
+ <span class="title">File: maintaining</span>
41
+
42
+ </div>
43
+
44
+ <div id="search">
45
+
46
+ <a class="full_list_link" id="class_list_link"
47
+ href="class_list.html">
48
+
49
+ <svg width="24" height="24">
50
+ <rect x="0" y="4" width="24" height="4" rx="1" ry="1"></rect>
51
+ <rect x="0" y="12" width="24" height="4" rx="1" ry="1"></rect>
52
+ <rect x="0" y="20" width="24" height="4" rx="1" ry="1"></rect>
53
+ </svg>
54
+ </a>
55
+
56
+ </div>
57
+ <div class="clear"></div>
58
+ </div>
59
+
60
+ <div id="content"><div id='filecontents'>
61
+ <p><a href="/README_md.html#guide--documentation">Back to the guide</a></p>
62
+
63
+ <h1 id="label-Maintaining+Compony">Maintaining Compony</h1>
64
+
65
+ <p>Conventions for contributors and AI assistants working <strong>on the gem itself</strong> (not apps using it). Keeps docs, gemspec and the rendered API reference from drifting.</p>
66
+
67
+ <h2 id="label-Every+change">Every change</h2>
68
+ <ul><li>
69
+ <p><strong>Behavior change → CHANGELOG.</strong> Add a bullet under the top <code># unreleased</code> heading in <a href="/CHANGELOG_md.html">CHANGELOG.md</a>. If it breaks existing apps, add a <code>## Steps to take</code> subsection with the migration (see prior entries for the format).</p>
70
+ </li><li>
71
+ <p><strong>New/renamed DSL method → docs.</strong> Update <a href="/doc/guide/dsl_reference_md.html">dsl_reference.md</a> (keep the <code># DSL method</code> source marker) and add a YARD summary with <code>@param</code>/<code>@return</code>/<code>@api</code> on the method.</p>
72
+ </li><li>
73
+ <p><strong>Comments only / docs only is fine to note as such</strong> in the CHANGELOG (“no behavior change”).</p>
74
+ </li></ul>
75
+
76
+ <h2 id="label-Releasing">Releasing</h2>
77
+ <ol><li>
78
+ <p>Bump the version in <code>lib/compony/version.rb</code>. Loading the Rakefile rewrites <code>VERSION</code> from it; <code>.edge</code> marks an unreleased prerelease.</p>
79
+ </li><li>
80
+ <p>Run <code>rake gemspec</code> — regenerates <code>compony.gemspec</code> (never hand-edit it; it says so).</p>
81
+ </li><li>
82
+ <p>Move the <code># unreleased</code> CHANGELOG block to a <code># X.Y.Z</code> heading; start a fresh <code># unreleased</code>.</p>
83
+ </li><li>
84
+ <p>Run <code>yard doc</code> and <strong>commit the regenerated <code>doc/*.html</code></strong> — the rendered API reference is committed and shipped in the gem (<code>s.files</code>), so stale HTML ships otherwise.</p>
85
+ </li><li>
86
+ <p><code>bundle exec rubocop</code> clean.</p>
87
+ </li><li>
88
+ <p>Tag / push / <code>gem build</code> per your release flow (<code>bundler/gem_tasks</code>).</p>
89
+ </li></ol>
90
+
91
+ <h2 id="label-Dependencies">Dependencies</h2>
92
+ <ul><li>
93
+ <p>Hard deps and their constraints live <strong>only</strong> in the <code>:gemspec</code> task in href="/Rakefile"></a>. Change them there, run <code>rake gemspec</code>, and update the mirror table in <a href="/doc/integrations_md.html">integrations.md</a> in the same commit.</p>
94
+ </li><li>
95
+ <p>Keep the README’s stated Rails/Ruby support in sync with <code>required_ruby_version</code> / the <code>rails</code> constraint — the gemspec is authoritative.</p>
96
+ </li></ul>
97
+
98
+ <h2 id="label-Documentation+rendering">Documentation rendering</h2>
99
+ <ul><li>
100
+ <p><code>doc/*.html</code> is generated by YARD from <code>lib/</code> + the extra files listed in href="/.yardopts"></a>.</p>
101
+ </li><li>
102
+ <p><strong>Adding a guide page?</strong> Add its path to <code>.yardopts</code> (after the <code>-</code> separator) or it will not appear in the rendered reference, then re-run <code>yard doc</code>.</p>
103
+ </li><li>
104
+ <p>Markdown changes to already-listed guide pages still need a <code>yard doc</code> re-run + commit to refresh the HTML.</p>
105
+ </li><li>
106
+ <p><code>yard doc</code> logs <code>Cannot resolve link to … from text:</code> for guide-to-guide Markdown links and inline <code>&lt;code&gt;</code> in the guide pages. This is <strong>expected and benign</strong> — YARD tries to treat them as Ruby code-object links. The pages render correctly and the links work on GitHub. Do not rewrite guide cross-links to silence YARD. (Genuine broken <code>{Xref}</code> in Ruby <code>lib/</code> comments are worth fixing; guide-Markdown link warnings are not.)</p>
107
+ </li></ul>
108
+
109
+ <h2 id="label-Patterns+derived+from+real+apps">Patterns derived from real apps</h2>
110
+ <ul><li>
111
+ <p><a href="/doc/guide/patterns_md.html">patterns.md</a> / <a href="/doc/guide/cookbook_md.html">cookbook.md</a> are <strong>fully anonymized</strong>: no app, business, author or domain-model names; neutral domain (<code>Account</code>, <code>Order</code>, <code>LineItem</code>, <code>Document</code>); app-wrapper-only APIs excluded or generalized (this is a public LGPL repo).</p>
112
+ </li><li>
113
+ <p>Document the <strong>secure</strong> variant only. Never reproduce an insecure shape (e.g. a capability token without expiry) even if that is what an app currently does — show the hardened form and call out the requirement.</p>
114
+ </li></ul>
115
+
116
+ <p><a href="/README_md.html#guide--documentation">Guide index</a></p>
117
+ </div></div>
118
+
119
+ <div id="footer">
120
+ Generated on Mon May 18 13:55:34 2026 by
121
+ <a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
122
+ 0.9.34 (ruby-3.3.5).
123
+ </div>
124
+
125
+ </div>
126
+ </body>
127
+ </html>
@@ -0,0 +1,137 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>
7
+ File: model_fields
8
+
9
+ &mdash; Documentation by YARD 0.9.34
10
+
11
+ </title>
12
+
13
+ <link rel="stylesheet" href="css/style.css" type="text/css" />
14
+
15
+ <link rel="stylesheet" href="css/common.css" type="text/css" />
16
+
17
+ <script type="text/javascript">
18
+ pathId = "model_fields";
19
+ relpath = '';
20
+ </script>
21
+
22
+
23
+ <script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
24
+
25
+ <script type="text/javascript" charset="utf-8" src="js/app.js"></script>
26
+
27
+
28
+ </head>
29
+ <body>
30
+ <div class="nav_wrap">
31
+ <iframe id="nav" src="file_list.html?1"></iframe>
32
+ <div id="resizer"></div>
33
+ </div>
34
+
35
+ <div id="main" tabindex="-1">
36
+ <div id="header">
37
+ <div id="menu">
38
+
39
+ <a href="_index.html">Index</a> &raquo;
40
+ <span class="title">File: model_fields</span>
41
+
42
+ </div>
43
+
44
+ <div id="search">
45
+
46
+ <a class="full_list_link" id="class_list_link"
47
+ href="class_list.html">
48
+
49
+ <svg width="24" height="24">
50
+ <rect x="0" y="4" width="24" height="4" rx="1" ry="1"></rect>
51
+ <rect x="0" y="12" width="24" height="4" rx="1" ry="1"></rect>
52
+ <rect x="0" y="20" width="24" height="4" rx="1" ry="1"></rect>
53
+ </svg>
54
+ </a>
55
+
56
+ </div>
57
+ <div class="clear"></div>
58
+ </div>
59
+
60
+ <div id="content"><div id='filecontents'>
61
+ <p><a href="/README_md.html#guide--documentation">Back to the guide</a></p>
62
+
63
+ <h1 id="label-Model+fields">Model fields</h1>
64
+
65
+ <p>Compony fields are your models’ attributes that you wish to expose in your application’s UI. They are a central place to store important information about those attributes, accessible from everywhere and without the need for a database connection.</p>
66
+
67
+ <p>Every Compony field must define at least a name and type. Compony types and ActiveRecord types are similar but not equivalent. While ActiveRecord uses types for storing data in the DB, Compony fields use them for presenting it. For instance, the Compony “string” type covers any kind of string, including ActiveRecord’s “string”, “text” etc. Similarly, Compony has no “numeric” type - use “integer” or “decimal” instead, depending on whether or not you want to show decimals or not. There are additional field types like “color”, “url” etc. You can find a complete list of all Compony field types in the module <code>Compony::ModelFields</code>.</p>
68
+
69
+ <p>Compony fields support Postgres arrays (non-nested).</p>
70
+
71
+ <p>A particularly interesting model field is <code>Association</code> which handles <code>belongs_to</code>, <code>has_many</code> and <code>has_one</code> associations, automatically resolving the association’s nature and providing links to the appropriate component.</p>
72
+
73
+ <p>Every Compony field can further take an arbitrary amount of additional named arguments. Those can be retrieved by calling <code>YourRailsModel.fields[:field_name].extra_attrs</code>.</p>
74
+
75
+ <p>Here is an example call to fields for a User model:</p>
76
+
77
+ <pre class="code ruby"><code class="ruby"><span class='comment'># app/models/user.rb
78
+ </span><span class='kw'>class</span> <span class='const'>User</span> <span class='op'>&lt;</span> <span class='const'>ApplicationRecord</span>
79
+ <span class='id identifier rubyid_field'>field</span> <span class='symbol'>:first_name</span><span class='comma'>,</span> <span class='symbol'>:string</span>
80
+ <span class='id identifier rubyid_field'>field</span> <span class='symbol'>:last_name</span><span class='comma'>,</span> <span class='symbol'>:string</span>
81
+ <span class='id identifier rubyid_field'>field</span> <span class='symbol'>:user_role</span><span class='comma'>,</span> <span class='symbol'>:anchormodel</span>
82
+ <span class='id identifier rubyid_field'>field</span> <span class='symbol'>:website</span><span class='comma'>,</span> <span class='symbol'>:url</span>
83
+ <span class='id identifier rubyid_field'>field</span> <span class='symbol'>:created_at</span><span class='comma'>,</span> <span class='symbol'>:datetime</span>
84
+ <span class='id identifier rubyid_field'>field</span> <span class='symbol'>:updated_at</span><span class='comma'>,</span> <span class='symbol'>:datetime</span>
85
+ <span class='kw'>end</span>
86
+ </code></pre>
87
+
88
+ <p>All fields declared this way are automatically exported as Rails Model attributes. Note that this also means that you should never declare <code>password</code> and <code>password_confirmation</code> as a Compony field, as you will get the ArgumentError “One or more password arguments are required” otherwise. Read more about handling password fields in the section about <code>Compony::Components::Form</code>.</p>
89
+
90
+ <p>Compony fields provide the following features:</p>
91
+ <ul><li>
92
+ <p>a label that lets you generate a name for the column: <code>User.fields[:first_name].label</code></p>
93
+ </li><li>
94
+ <p><code>value_for</code>: given a model instance, formats the data (e.g. a field of type “url” will produce a link).</p>
95
+ </li><li>
96
+ <p>Features for forms:</p>
97
+ </li><li>
98
+ <p><code>simpleform_input</code> auto-generates in input for a simple form (from the <code>simple_form</code> gem).</p>
99
+ </li><li>
100
+ <p><code>simpleform_input_hidden</code> auto-generates a hidden input.</p>
101
+ </li><li>
102
+ <p><code>schema_line</code> auto-generates a DSL call for Schemacop v3 (from the <code>schemacop</code> gem), which is useful for parameter validation.</p>
103
+ </li></ul>
104
+
105
+ <p>You can then use these fields in other components, for instance a list as described in the example at the top of this guide:</p>
106
+
107
+ <pre class="code ruby"><code class="ruby"><span class='const'>User</span><span class='period'>.</span><span class='id identifier rubyid_fields'>fields</span><span class='period'>.</span><span class='id identifier rubyid_values'>values</span><span class='period'>.</span><span class='id identifier rubyid_each'>each</span> <span class='kw'>do</span> <span class='op'>|</span><span class='id identifier rubyid_field'>field</span><span class='op'>|</span>
108
+ <span class='id identifier rubyid_span'>span</span> <span class='kw'>do</span>
109
+ <span class='id identifier rubyid_concat'>concat</span> <span class='tstring'><span class='tstring_beg'>&quot;</span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_field'>field</span><span class='period'>.</span><span class='id identifier rubyid_label'>label</span><span class='embexpr_end'>}</span><span class='tstring_content'>: </span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_field'>field</span><span class='period'>.</span><span class='id identifier rubyid_value_for'>value_for</span><span class='lparen'>(</span><span class='id identifier rubyid_user'>user</span><span class='rparen'>)</span><span class='embexpr_end'>}</span><span class='tstring_content'> </span><span class='tstring_end'>&quot;</span></span> <span class='comment'># Display the field&#39;s label and apply it to value
110
+ </span> <span class='kw'>end</span>
111
+ <span class='kw'>end</span>
112
+ </code></pre>
113
+
114
+ <h2 id="label-Implementing+your+own+fields">Implementing your own fields</h2>
115
+
116
+ <p>You can implement your own model fields. Make sure they are all within the same namespace and inherit at least from <code>Compony::ModelFields::Base</code>. To enable them, write an initializer that overwrites the array <code>Compony.model_field_namespaces</code>. Namespaces listed in the array are prioritized from first to last. If a field (e.g. <code>String</code>) exists in multiple declared namespaces, the first will be used. This allows you to overwrite Compony fields.</p>
117
+
118
+ <p>Example:</p>
119
+
120
+ <pre class="code ruby"><code class="ruby"><span class='comment'># config/initializers/compony.rb
121
+ </span><span class='const'><span class='object_link'><a href="Compony.html" title="Compony (module)">Compony</a></span></span><span class='period'>.</span><span class='id identifier rubyid_model_field_namespaces'><span class='object_link'><a href="Compony.html#model_field_namespaces-class_method" title="Compony.model_field_namespaces (method)">model_field_namespaces</a></span></span> <span class='op'>=</span> <span class='lbracket'>[</span><span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>MyCustomModelFields</span><span class='tstring_end'>&#39;</span></span><span class='comma'>,</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>Compony::ModelFields</span><span class='tstring_end'>&#39;</span></span><span class='rbracket'>]</span>
122
+ </code></pre>
123
+
124
+ <p>You can then implement <code>MyCustomModelFields::Animal</code>, <code>MyCustomModelFields::String</code> etc. You can then use <code>field :fav_animal, :animal</code> in your model.</p>
125
+
126
+ <p><a href="/README_md.html#guide--documentation">Guide index</a></p>
127
+ </div></div>
128
+
129
+ <div id="footer">
130
+ Generated on Mon May 18 13:55:33 2026 by
131
+ <a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
132
+ 0.9.34 (ruby-3.3.5).
133
+ </div>
134
+
135
+ </div>
136
+ </body>
137
+ </html>