anchormodel 0.3.1 → 0.4.0

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 (43) hide show
  1. checksums.yaml +4 -4
  2. data/.ruby-version +1 -1
  3. data/CHANGELOG.md +14 -0
  4. data/EXAMPLES.md +408 -0
  5. data/Gemfile.lock +1 -1
  6. data/README.md +43 -1
  7. data/VERSION +1 -1
  8. data/anchormodel.gemspec +3 -3
  9. data/bin/test +9 -0
  10. data/doc/Anchormodel/ActiveModelTypeValueMulti.html +204 -42
  11. data/doc/Anchormodel/ActiveModelTypeValueSingle.html +243 -54
  12. data/doc/Anchormodel/Attribute.html +60 -37
  13. data/doc/Anchormodel/ModelMixin.html +166 -16
  14. data/doc/Anchormodel/SimpleFormInputs/Helpers/AnchormodelInputsCommon.html +82 -21
  15. data/doc/Anchormodel/SimpleFormInputs/Helpers.html +2 -11
  16. data/doc/Anchormodel/SimpleFormInputs.html +2 -11
  17. data/doc/Anchormodel/Util.html +497 -38
  18. data/doc/Anchormodel/Version.html +2 -20
  19. data/doc/Anchormodel.html +536 -129
  20. data/doc/AnchormodelCheckBoxesInput.html +22 -1
  21. data/doc/AnchormodelGenerator.html +64 -13
  22. data/doc/AnchormodelInput.html +24 -1
  23. data/doc/AnchormodelRadioButtonsInput.html +22 -1
  24. data/doc/_index.html +16 -1
  25. data/doc/class_list.html +1 -1
  26. data/doc/file.README.html +40 -2
  27. data/doc/index.html +40 -2
  28. data/doc/method_list.html +57 -17
  29. data/doc/top-level-namespace.html +1 -1
  30. data/lib/anchormodel/active_model_type_value_multi.rb +31 -5
  31. data/lib/anchormodel/active_model_type_value_single.rb +34 -6
  32. data/lib/anchormodel/attribute.rb +20 -8
  33. data/lib/anchormodel/model_mixin.rb +43 -8
  34. data/lib/anchormodel/simple_form_inputs/anchormodel_check_boxes_input.rb +7 -0
  35. data/lib/anchormodel/simple_form_inputs/anchormodel_input.rb +9 -0
  36. data/lib/anchormodel/simple_form_inputs/anchormodel_radio_buttons_input.rb +7 -0
  37. data/lib/anchormodel/simple_form_inputs/helpers/anchormodel_inputs_common.rb +14 -0
  38. data/lib/anchormodel/util.rb +102 -17
  39. data/lib/anchormodel.rb +109 -15
  40. data/lib/generators/anchormodel/anchormodel_generator.rb +8 -0
  41. data/test/active_record_model/user_test.rb +221 -10
  42. data/test/dummy/app/anchormodels/animal.rb +1 -0
  43. metadata +3 -1
@@ -86,7 +86,7 @@
86
86
  <h2>Overview</h2><div class="docstring">
87
87
  <div class="discussion">
88
88
 
89
- <p>A swiss army knife for common functionality</p>
89
+ <p>Internal utilities used by the ModelMixin#belongs_to_anchormodel and ModelMixin#belongs_to_anchormodels macros. The public-facing entry points are the macros themselves; methods here are the wiring that installs the generated readers, writers, scopes, type casters, and helper scopes.</p>
90
90
 
91
91
 
92
92
  </div>
@@ -112,7 +112,55 @@
112
112
  <li class="public ">
113
113
  <span class="summary_signature">
114
114
 
115
- <a href="#install_methods_in_model-class_method" title="install_methods_in_model (class method)">.<strong>install_methods_in_model</strong>(model_class, attribute_name, anchormodel_class = nil, optional: false, multiple: false, model_readers: true, model_writers: true, model_scopes: true, model_methods: nil) &#x21d2; Object </a>
115
+ <a href="#csv_contains_like-class_method" title="csv_contains_like (class method)">.<strong>csv_contains_like</strong>(attribute, key) &#x21d2; Array(String, *String) </a>
116
+
117
+
118
+
119
+ </span>
120
+
121
+
122
+
123
+
124
+
125
+
126
+
127
+
128
+
129
+ <span class="summary_desc"><div class='inline'>
130
+ <p>Builds a <code>WHERE</code> fragment matching rows whose CSV-stored <code>attribute</code> column contains <code>key</code>.</p>
131
+ </div></span>
132
+
133
+ </li>
134
+
135
+
136
+ <li class="public ">
137
+ <span class="summary_signature">
138
+
139
+ <a href="#escape_like-class_method" title="escape_like (class method)">.<strong>escape_like</strong>(str) &#x21d2; String </a>
140
+
141
+
142
+
143
+ </span>
144
+
145
+
146
+
147
+
148
+
149
+
150
+
151
+
152
+
153
+ <span class="summary_desc"><div class='inline'>
154
+ <p>Escapes <code>_</code>, <code>%</code>, and <code>!</code> so the string can be used as a literal inside a SQL <code>LIKE</code> pattern paired with <code>ESCAPE &#39;!&#39;</code>.</p>
155
+ </div></span>
156
+
157
+ </li>
158
+
159
+
160
+ <li class="public ">
161
+ <span class="summary_signature">
162
+
163
+ <a href="#install_methods_in_model-class_method" title="install_methods_in_model (class method)">.<strong>install_methods_in_model</strong>(model_class, attribute_name, anchormodel_class = nil, optional: false, multiple: false, model_readers: true, model_writers: true, model_scopes: true, model_methods: nil) &#x21d2; void </a>
116
164
 
117
165
 
118
166
 
@@ -130,6 +178,30 @@
130
178
  <p>Installs an anchormodel attribute in a model class.</p>
131
179
  </div></span>
132
180
 
181
+ </li>
182
+
183
+
184
+ <li class="public ">
185
+ <span class="summary_signature">
186
+
187
+ <a href="#normalize_anchormodel_keys-class_method" title="normalize_anchormodel_keys (class method)">.<strong>normalize_anchormodel_keys</strong>(keys, anchormodel_class) &#x21d2; Array&lt;String&gt; </a>
188
+
189
+
190
+
191
+ </span>
192
+
193
+
194
+
195
+
196
+
197
+
198
+
199
+
200
+
201
+ <span class="summary_desc"><div class='inline'>
202
+ <p>Coerces a list of mixed-type key inputs into validated key Strings, ready for SQL binding.</p>
203
+ </div></span>
204
+
133
205
  </li>
134
206
 
135
207
 
@@ -143,9 +215,123 @@
143
215
 
144
216
 
145
217
  <div class="method_details first">
146
- <h3 class="signature first" id="install_methods_in_model-class_method">
218
+ <h3 class="signature first" id="csv_contains_like-class_method">
219
+
220
+ .<strong>csv_contains_like</strong>(attribute, key) &#x21d2; <tt>Array(String, *String)</tt>
221
+
222
+
223
+
224
+
225
+
226
+ </h3><div class="docstring">
227
+ <div class="discussion">
228
+
229
+ <p>Builds a <code>WHERE</code> fragment matching rows whose CSV-stored <code>attribute</code> column contains <code>key</code>. Generates four predicates OR’d together to cover the cases where <code>key</code> appears at the start, end, middle, or as the sole entry in the CSV.</p>
230
+
231
+ <p><code>_</code> and <code>%</code> characters in <code>key</code> are escaped via <code>ESCAPE &#39;!&#39;</code> so that LIKE wildcards in the key (e.g. <code>:big_cat</code>) are treated literally instead of cross-matching arbitrary column values like <code>&quot;bigXcat,foo&quot;</code>.</p>
232
+
233
+
234
+ </div>
235
+ </div>
236
+ <div class="tags">
237
+
238
+ <div class="examples">
239
+ <p class="tag_title">Examples:</p>
240
+
241
+
242
+ <pre class="example code"><code><span class='id identifier rubyid_sql'>sql</span><span class='comma'>,</span> <span class='op'>*</span><span class='id identifier rubyid_binds'>binds</span> <span class='op'>=</span> <span class='const'><span class='object_link'><a href="../Anchormodel.html" title="Anchormodel (class)">Anchormodel</a></span></span><span class='op'>::</span><span class='const'><span class='object_link'><a href="" title="Anchormodel::Util (module)">Util</a></span></span><span class='period'>.</span><span class='id identifier rubyid_csv_contains_like'>csv_contains_like</span><span class='lparen'>(</span><span class='symbol'>:animals</span><span class='comma'>,</span> <span class='symbol'>:cat</span><span class='rparen'>)</span>
243
+ <span class='const'>User</span><span class='period'>.</span><span class='id identifier rubyid_where'>where</span><span class='lparen'>(</span><span class='id identifier rubyid_sql'>sql</span><span class='comma'>,</span> <span class='op'>*</span><span class='id identifier rubyid_binds'>binds</span><span class='rparen'>)</span></code></pre>
244
+
245
+ </div>
246
+ <p class="tag_title">Parameters:</p>
247
+ <ul class="param">
147
248
 
148
- .<strong>install_methods_in_model</strong>(model_class, attribute_name, anchormodel_class = nil, optional: false, multiple: false, model_readers: true, model_writers: true, model_scopes: true, model_methods: nil) &#x21d2; <tt>Object</tt>
249
+ <li>
250
+
251
+ <span class='name'>attribute</span>
252
+
253
+
254
+ <span class='type'>(<tt>String</tt>, <tt>Symbol</tt>)</span>
255
+
256
+
257
+
258
+ &mdash;
259
+ <div class='inline'>
260
+ <p>Column name to query.</p>
261
+ </div>
262
+
263
+ </li>
264
+
265
+ <li>
266
+
267
+ <span class='name'>key</span>
268
+
269
+
270
+ <span class='type'>(<tt>String</tt>, <tt>Symbol</tt>)</span>
271
+
272
+
273
+
274
+ &mdash;
275
+ <div class='inline'>
276
+ <p>Key to search for inside the CSV column value.</p>
277
+ </div>
278
+
279
+ </li>
280
+
281
+ </ul>
282
+
283
+ <p class="tag_title">Returns:</p>
284
+ <ul class="return">
285
+
286
+ <li>
287
+
288
+
289
+ <span class='type'>(<tt>Array(String, *String)</tt>)</span>
290
+
291
+
292
+
293
+ &mdash;
294
+ <div class='inline'>
295
+ <p><code>[sql_fragment, *bind_values]</code>, suitable for splatting into <code>Model.where(sql, *binds)</code>.</p>
296
+ </div>
297
+
298
+ </li>
299
+
300
+ </ul>
301
+
302
+ </div><table class="source_code">
303
+ <tr>
304
+ <td>
305
+ <pre class="lines">
306
+
307
+
308
+ 214
309
+ 215
310
+ 216
311
+ 217
312
+ 218
313
+ 219
314
+ 220</pre>
315
+ </td>
316
+ <td>
317
+ <pre class="code"><span class="info file"># File 'lib/anchormodel/util.rb', line 214</span>
318
+
319
+ <span class='kw'>def</span> <span class='kw'>self</span><span class='period'>.</span><span class='id identifier rubyid_csv_contains_like'>csv_contains_like</span><span class='lparen'>(</span><span class='id identifier rubyid_attribute'>attribute</span><span class='comma'>,</span> <span class='id identifier rubyid_key'>key</span><span class='rparen'>)</span>
320
+ <span class='id identifier rubyid_escaped'>escaped</span> <span class='op'>=</span> <span class='id identifier rubyid_escape_like'>escape_like</span><span class='lparen'>(</span><span class='id identifier rubyid_key'>key</span><span class='period'>.</span><span class='id identifier rubyid_to_s'>to_s</span><span class='rparen'>)</span>
321
+ <span class='id identifier rubyid_sql'>sql</span> <span class='op'>=</span> <span class='tstring'><span class='tstring_beg'>&quot;</span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_attribute'>attribute</span><span class='embexpr_end'>}</span><span class='tstring_content'> = ? OR </span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_attribute'>attribute</span><span class='embexpr_end'>}</span><span class='tstring_content'> LIKE ? ESCAPE &#39;!&#39; </span><span class='tstring_end'>&quot;</span></span> \
322
+ <span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>OR </span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_attribute'>attribute</span><span class='embexpr_end'>}</span><span class='tstring_content'> LIKE ? ESCAPE &#39;!&#39; OR </span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_attribute'>attribute</span><span class='embexpr_end'>}</span><span class='tstring_content'> LIKE ? ESCAPE &#39;!&#39;</span><span class='tstring_end'>&quot;</span></span>
323
+ <span class='id identifier rubyid_binds'>binds</span> <span class='op'>=</span> <span class='lbracket'>[</span><span class='id identifier rubyid_key'>key</span><span class='period'>.</span><span class='id identifier rubyid_to_s'>to_s</span><span class='comma'>,</span> <span class='tstring'><span class='tstring_beg'>&quot;</span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_escaped'>escaped</span><span class='embexpr_end'>}</span><span class='tstring_content'>,%</span><span class='tstring_end'>&quot;</span></span><span class='comma'>,</span> <span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>%,</span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_escaped'>escaped</span><span class='embexpr_end'>}</span><span class='tstring_end'>&quot;</span></span><span class='comma'>,</span> <span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>%,</span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_escaped'>escaped</span><span class='embexpr_end'>}</span><span class='tstring_content'>,%</span><span class='tstring_end'>&quot;</span></span><span class='rbracket'>]</span>
324
+ <span class='lbracket'>[</span><span class='id identifier rubyid_sql'>sql</span><span class='comma'>,</span> <span class='op'>*</span><span class='id identifier rubyid_binds'>binds</span><span class='rbracket'>]</span>
325
+ <span class='kw'>end</span></pre>
326
+ </td>
327
+ </tr>
328
+ </table>
329
+ </div>
330
+
331
+ <div class="method_details ">
332
+ <h3 class="signature " id="escape_like-class_method">
333
+
334
+ .<strong>escape_like</strong>(str) &#x21d2; <tt>String</tt>
149
335
 
150
336
 
151
337
 
@@ -154,7 +340,96 @@
154
340
  </h3><div class="docstring">
155
341
  <div class="discussion">
156
342
 
157
- <p>Installs an anchormodel attribute in a model class</p>
343
+ <p>Escapes <code>_</code>, <code>%</code>, and <code>!</code> so the string can be used as a literal inside a SQL <code>LIKE</code> pattern paired with <code>ESCAPE &#39;!&#39;</code>. Uses <code>!</code> rather than the conventional &lt;code&gt;&lt;/code&gt; to avoid the cross-DB ambiguity of backslash inside SQL string literals (SQLite vs MySQL vs PostgreSQL all differ).</p>
344
+
345
+
346
+ </div>
347
+ </div>
348
+ <div class="tags">
349
+
350
+ <div class="examples">
351
+ <p class="tag_title">Examples:</p>
352
+
353
+
354
+ <pre class="example code"><code><span class='const'><span class='object_link'><a href="../Anchormodel.html" title="Anchormodel (class)">Anchormodel</a></span></span><span class='op'>::</span><span class='const'><span class='object_link'><a href="" title="Anchormodel::Util (module)">Util</a></span></span><span class='period'>.</span><span class='id identifier rubyid_escape_like'>escape_like</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>big_cat</span><span class='tstring_end'>&#39;</span></span><span class='rparen'>)</span> <span class='comment'># =&gt; &quot;big!_cat&quot;</span></code></pre>
355
+
356
+ </div>
357
+ <p class="tag_title">Parameters:</p>
358
+ <ul class="param">
359
+
360
+ <li>
361
+
362
+ <span class='name'>str</span>
363
+
364
+
365
+ <span class='type'>(<tt>String</tt>, <tt>Symbol</tt>)</span>
366
+
367
+
368
+
369
+ &mdash;
370
+ <div class='inline'>
371
+ <p>Input to escape.</p>
372
+ </div>
373
+
374
+ </li>
375
+
376
+ </ul>
377
+
378
+ <p class="tag_title">Returns:</p>
379
+ <ul class="return">
380
+
381
+ <li>
382
+
383
+
384
+ <span class='type'>(<tt>String</tt>)</span>
385
+
386
+
387
+
388
+ &mdash;
389
+ <div class='inline'>
390
+ <p>Escaped string.</p>
391
+ </div>
392
+
393
+ </li>
394
+
395
+ </ul>
396
+
397
+ </div><table class="source_code">
398
+ <tr>
399
+ <td>
400
+ <pre class="lines">
401
+
402
+
403
+ 231
404
+ 232
405
+ 233</pre>
406
+ </td>
407
+ <td>
408
+ <pre class="code"><span class="info file"># File 'lib/anchormodel/util.rb', line 231</span>
409
+
410
+ <span class='kw'>def</span> <span class='kw'>self</span><span class='period'>.</span><span class='id identifier rubyid_escape_like'>escape_like</span><span class='lparen'>(</span><span class='id identifier rubyid_str'>str</span><span class='rparen'>)</span>
411
+ <span class='id identifier rubyid_str'>str</span><span class='period'>.</span><span class='id identifier rubyid_to_s'>to_s</span><span class='period'>.</span><span class='id identifier rubyid_gsub'>gsub</span><span class='lparen'>(</span><span class='tstring'><span class='regexp_beg'>/</span><span class='tstring_content'>[!%_]</span><span class='regexp_end'>/</span></span><span class='rparen'>)</span> <span class='lbrace'>{</span> <span class='op'>|</span><span class='id identifier rubyid_c'>c</span><span class='op'>|</span> <span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>!</span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_c'>c</span><span class='embexpr_end'>}</span><span class='tstring_end'>&quot;</span></span> <span class='rbrace'>}</span>
412
+ <span class='kw'>end</span></pre>
413
+ </td>
414
+ </tr>
415
+ </table>
416
+ </div>
417
+
418
+ <div class="method_details ">
419
+ <h3 class="signature " id="install_methods_in_model-class_method">
420
+
421
+ .<strong>install_methods_in_model</strong>(model_class, attribute_name, anchormodel_class = nil, optional: false, multiple: false, model_readers: true, model_writers: true, model_scopes: true, model_methods: nil) &#x21d2; <tt>void</tt>
422
+
423
+
424
+
425
+
426
+
427
+ </h3><div class="docstring">
428
+ <div class="discussion">
429
+ <p class="note returns_void">This method returns an undefined value.</p>
430
+ <p>Installs an anchormodel attribute in a model class. Wires up the AR <code>attribute</code> type cast, the custom reader/writer, the per-key readers/writers/scopes, and (for <code>belongs_to_anchormodels</code>) the bulk-key <code>with_any_&lt;attr&gt;</code> / <code>with_all_&lt;attr&gt;</code> scopes.</p>
431
+
432
+ <p>Called from ModelMixin#belongs_to_anchormodel and ModelMixin#belongs_to_anchormodels. Not normally invoked directly.</p>
158
433
 
159
434
 
160
435
  </div>
@@ -168,13 +443,13 @@
168
443
  <span class='name'>model_class</span>
169
444
 
170
445
 
171
- <span class='type'>(<tt>ActiveRecord::Base</tt>)</span>
446
+ <span class='type'>(<tt>Class</tt>)</span>
172
447
 
173
448
 
174
449
 
175
450
  &mdash;
176
451
  <div class='inline'>
177
- <p>Internal only. The model class that the attribute should be installed to.</p>
452
+ <p>Internal only. The model class the attribute is installed on.</p>
178
453
  </div>
179
454
 
180
455
  </li>
@@ -190,7 +465,7 @@
190
465
 
191
466
  &mdash;
192
467
  <div class='inline'>
193
- <p>The name and database column of the attribute</p>
468
+ <p>The name and database column of the attribute.</p>
194
469
  </div>
195
470
 
196
471
  </li>
@@ -200,7 +475,7 @@
200
475
  <span class='name'>anchormodel_class</span>
201
476
 
202
477
 
203
- <span class='type'>(<tt>Class</tt>)</span>
478
+ <span class='type'>(<tt>Class</tt>, <tt>nil</tt>)</span>
204
479
 
205
480
 
206
481
  <em class="default">(defaults to: <tt>nil</tt>)</em>
@@ -208,7 +483,7 @@
208
483
 
209
484
  &mdash;
210
485
  <div class='inline'>
211
- <p>Class of the Anchormodel (omit if attribute <code>:foo_bar</code> holds a <code>FooBar</code>)</p>
486
+ <p>The anchormodel class. If omitted, inferred from <code>attribute_name</code> (<code>:foo_bar</code> <code>FooBar</code>).</p>
212
487
  </div>
213
488
 
214
489
  </li>
@@ -226,7 +501,7 @@
226
501
 
227
502
  &mdash;
228
503
  <div class='inline'>
229
- <p>If false, a presence validation is added to the model. Forced to true if multiple is true.</p>
504
+ <p>If false, a presence validation is added to the model. Forced to true when <code>multiple</code> is true.</p>
230
505
  </div>
231
506
 
232
507
  </li>
@@ -244,7 +519,7 @@
244
519
 
245
520
  &mdash;
246
521
  <div class='inline'>
247
- <p>Internal only. Distinguishes between <code>belongs_to_anchormodel</code> and <code>belongs_to_anchormodels</code>.</p>
522
+ <p>Internal only. Distinguishes between <code>belongs_to_anchormodel</code> (false) and <code>belongs_to_anchormodels</code> (true).</p>
248
523
  </div>
249
524
 
250
525
  </li>
@@ -262,7 +537,7 @@
262
537
 
263
538
  &mdash;
264
539
  <div class='inline'>
265
- <p>If true, the model is given an ActiveRecord::Enum style method <code>my_model.my_key?</code> reader for each key in the anchormodel</p>
540
+ <p>If true, generates <code>model.key?</code> readers per anchormodel key.</p>
266
541
  </div>
267
542
 
268
543
  </li>
@@ -280,7 +555,7 @@
280
555
 
281
556
  &mdash;
282
557
  <div class='inline'>
283
- <p>If true, the model is given an ActiveRecord::Enum style method <code>my_model.my_key!</code> writer for each key in the anchormodel</p>
558
+ <p>If true, generates <code>model.key!</code> writers per anchormodel key.</p>
284
559
  </div>
285
560
 
286
561
  </li>
@@ -298,7 +573,7 @@
298
573
 
299
574
  &mdash;
300
575
  <div class='inline'>
301
- <p>If true, the model is given an ActiveRecord::Enum style scope <code>MyModel.mykey</code> for each key in the anchormodel</p>
576
+ <p>If true, generates <code>Model.key</code> scopes per anchormodel key.</p>
302
577
  </div>
303
578
 
304
579
  </li>
@@ -308,7 +583,7 @@
308
583
  <span class='name'>model_methods</span>
309
584
 
310
585
 
311
- <span class='type'>(<tt>Boolean</tt>, <tt>NilClass</tt>)</span>
586
+ <span class='type'>(<tt>Boolean</tt>, <tt>nil</tt>)</span>
312
587
 
313
588
 
314
589
  <em class="default">(defaults to: <tt>nil</tt>)</em>
@@ -316,13 +591,31 @@
316
591
 
317
592
  &mdash;
318
593
  <div class='inline'>
319
- <p>If non-nil, this mass-assigns and overrides <code>model_readers</code>, <code>model_writers</code> and <code>model_scopes</code></p>
594
+ <p>If non-nil, mass-overrides <code>model_readers</code>/<code>model_writers</code>/<code>model_scopes</code>.</p>
320
595
  </div>
321
596
 
322
597
  </li>
323
598
 
324
599
  </ul>
325
600
 
601
+ <p class="tag_title">Raises:</p>
602
+ <ul class="raise">
603
+
604
+ <li>
605
+
606
+
607
+ <span class='type'>(<tt>RuntimeError</tt>)</span>
608
+
609
+
610
+
611
+ &mdash;
612
+ <div class='inline'>
613
+ <p>if a generated method or scope name collides with an existing one.</p>
614
+ </div>
615
+
616
+ </li>
617
+
618
+ </ul>
326
619
 
327
620
  </div><table class="source_code">
328
621
  <tr>
@@ -330,19 +623,6 @@
330
623
  <pre class="lines">
331
624
 
332
625
 
333
- 14
334
- 15
335
- 16
336
- 17
337
- 18
338
- 19
339
- 20
340
- 21
341
- 22
342
- 23
343
- 24
344
- 25
345
- 26
346
626
  27
347
627
  28
348
628
  29
@@ -464,10 +744,43 @@
464
744
  145
465
745
  146
466
746
  147
467
- 148</pre>
747
+ 148
748
+ 149
749
+ 150
750
+ 151
751
+ 152
752
+ 153
753
+ 154
754
+ 155
755
+ 156
756
+ 157
757
+ 158
758
+ 159
759
+ 160
760
+ 161
761
+ 162
762
+ 163
763
+ 164
764
+ 165
765
+ 166
766
+ 167
767
+ 168
768
+ 169
769
+ 170
770
+ 171
771
+ 172
772
+ 173
773
+ 174
774
+ 175
775
+ 176
776
+ 177
777
+ 178
778
+ 179
779
+ 180
780
+ 181</pre>
468
781
  </td>
469
782
  <td>
470
- <pre class="code"><span class="info file"># File 'lib/anchormodel/util.rb', line 14</span>
783
+ <pre class="code"><span class="info file"># File 'lib/anchormodel/util.rb', line 27</span>
471
784
 
472
785
  <span class='kw'>def</span> <span class='kw'>self</span><span class='period'>.</span><span class='id identifier rubyid_install_methods_in_model'>install_methods_in_model</span><span class='lparen'>(</span><span class='id identifier rubyid_model_class'>model_class</span><span class='comma'>,</span> <span class='id identifier rubyid_attribute_name'>attribute_name</span><span class='comma'>,</span> <span class='id identifier rubyid_anchormodel_class'>anchormodel_class</span> <span class='op'>=</span> <span class='kw'>nil</span><span class='comma'>,</span>
473
786
  <span class='label'>optional:</span> <span class='kw'>false</span><span class='comma'>,</span>
@@ -587,22 +900,168 @@
587
900
  <span class='kw'>end</span>
588
901
 
589
902
  <span class='comment'># Create ActiveRecord::Enum style scope directly in the model class if asked to do so
590
- </span> <span class='comment'># For a model User with anchormodel Role with keys :admin and :guest, this creates user.admin! and user.guest! (setting the role to admin/guest)
903
+ </span> <span class='comment'># For a model User with anchormodel Role with keys :admin and :guest, this creates User.admin and User.guest scopes
591
904
  </span> <span class='kw'>if</span> <span class='id identifier rubyid_model_scopes'>model_scopes</span>
592
905
  <span class='id identifier rubyid_anchormodel_class'>anchormodel_class</span><span class='period'>.</span><span class='id identifier rubyid_all'>all</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_entry'>entry</span><span class='op'>|</span>
593
906
  <span class='kw'>if</span> <span class='id identifier rubyid_model_class'>model_class</span><span class='period'>.</span><span class='id identifier rubyid_respond_to?'>respond_to?</span><span class='lparen'>(</span><span class='id identifier rubyid_entry'>entry</span><span class='period'>.</span><span class='id identifier rubyid_key'>key</span><span class='rparen'>)</span>
594
907
  <span class='id identifier rubyid_fail'>fail</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>Anchormodel scope </span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_entry'>entry</span><span class='period'>.</span><span class='id identifier rubyid_key'>key</span><span class='embexpr_end'>}</span><span class='tstring_content'> already defined for </span><span class='embexpr_beg'>#{</span><span class='kw'>self</span><span class='embexpr_end'>}</span><span class='tstring_content'>, add `model_scopes: false` to `belongs_to_anchormodel :</span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_attribute_name'>attribute_name</span><span class='embexpr_end'>}</span><span class='tstring_content'>`.</span><span class='tstring_end'>&quot;</span></span><span class='rparen'>)</span>
595
908
  <span class='kw'>end</span>
596
909
  <span class='kw'>if</span> <span class='id identifier rubyid_multiple'>multiple</span>
597
- <span class='id identifier rubyid_model_class'>model_class</span><span class='period'>.</span><span class='id identifier rubyid_scope'>scope</span><span class='lparen'>(</span><span class='id identifier rubyid_entry'>entry</span><span class='period'>.</span><span class='id identifier rubyid_key'>key</span><span class='comma'>,</span> <span class='id identifier rubyid_lambda'>lambda</span> <span class='lbrace'>{</span>
598
- <span class='id identifier rubyid_where'>where</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&quot;</span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_attribute_name'>attribute_name</span><span class='embexpr_end'>}</span><span class='tstring_content'> LIKE ? OR </span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_attribute_name'>attribute_name</span><span class='embexpr_end'>}</span><span class='tstring_content'> LIKE ? OR </span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_attribute_name'>attribute_name</span><span class='embexpr_end'>}</span><span class='tstring_content'> LIKE ? OR </span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_attribute_name'>attribute_name</span><span class='embexpr_end'>}</span><span class='tstring_content'> LIKE ?</span><span class='tstring_end'>&quot;</span></span><span class='comma'>,</span>
599
- <span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>%</span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_entry'>entry</span><span class='period'>.</span><span class='id identifier rubyid_key'>key</span><span class='embexpr_end'>}</span><span class='tstring_content'>,%</span><span class='tstring_end'>&quot;</span></span><span class='comma'>,</span> <span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>%</span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_entry'>entry</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><span class='comma'>,</span> <span class='tstring'><span class='tstring_beg'>&quot;</span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_entry'>entry</span><span class='period'>.</span><span class='id identifier rubyid_key'>key</span><span class='embexpr_end'>}</span><span class='tstring_content'>,%</span><span class='tstring_end'>&quot;</span></span><span class='comma'>,</span> <span class='id identifier rubyid_entry'>entry</span><span class='period'>.</span><span class='id identifier rubyid_key'>key</span><span class='period'>.</span><span class='id identifier rubyid_to_s'>to_s</span><span class='rparen'>)</span>
600
- <span class='rbrace'>}</span><span class='rparen'>)</span>
910
+ <span class='id identifier rubyid_sql'>sql</span><span class='comma'>,</span> <span class='op'>*</span><span class='id identifier rubyid_binds'>binds</span> <span class='op'>=</span> <span class='const'><span class='object_link'><a href="../Anchormodel.html" title="Anchormodel (class)">Anchormodel</a></span></span><span class='op'>::</span><span class='const'><span class='object_link'><a href="" title="Anchormodel::Util (module)">Util</a></span></span><span class='period'>.</span><span class='id identifier rubyid_csv_contains_like'><span class='object_link'><a href="#csv_contains_like-class_method" title="Anchormodel::Util.csv_contains_like (method)">csv_contains_like</a></span></span><span class='lparen'>(</span><span class='id identifier rubyid_attribute_name'>attribute_name</span><span class='comma'>,</span> <span class='id identifier rubyid_entry'>entry</span><span class='period'>.</span><span class='id identifier rubyid_key'>key</span><span class='rparen'>)</span>
911
+ <span class='id identifier rubyid_model_class'>model_class</span><span class='period'>.</span><span class='id identifier rubyid_scope'>scope</span><span class='lparen'>(</span><span class='id identifier rubyid_entry'>entry</span><span class='period'>.</span><span class='id identifier rubyid_key'>key</span><span class='comma'>,</span> <span class='tlambda'>-&gt;</span> <span class='tlambeg'>{</span> <span class='id identifier rubyid_where'>where</span><span class='lparen'>(</span><span class='id identifier rubyid_sql'>sql</span><span class='comma'>,</span> <span class='op'>*</span><span class='id identifier rubyid_binds'>binds</span><span class='rparen'>)</span> <span class='rbrace'>}</span><span class='rparen'>)</span>
601
912
  <span class='kw'>else</span>
602
913
  <span class='id identifier rubyid_model_class'>model_class</span><span class='period'>.</span><span class='id identifier rubyid_scope'>scope</span><span class='lparen'>(</span><span class='id identifier rubyid_entry'>entry</span><span class='period'>.</span><span class='id identifier rubyid_key'>key</span><span class='comma'>,</span> <span class='tlambda'>-&gt;</span> <span class='tlambeg'>{</span> <span class='id identifier rubyid_where'>where</span><span class='lparen'>(</span><span class='id identifier rubyid_attribute_name'>attribute_name</span> <span class='op'>=&gt;</span> <span class='id identifier rubyid_entry'>entry</span><span class='period'>.</span><span class='id identifier rubyid_key'>key</span><span class='rparen'>)</span> <span class='rbrace'>}</span><span class='rparen'>)</span>
603
914
  <span class='kw'>end</span>
604
915
  <span class='kw'>end</span>
605
916
  <span class='kw'>end</span>
917
+
918
+ <span class='comment'># For `belongs_to_anchormodels`, add bulk-key scopes since `where(col: array)` cannot
919
+ </span> <span class='comment'># match CSV-in-column storage. Defined regardless of `model_scopes` — they are bulk
920
+ </span> <span class='comment'># query helpers, not per-key scopes.
921
+ </span> <span class='kw'>if</span> <span class='id identifier rubyid_multiple'>multiple</span>
922
+ <span class='id identifier rubyid_model_class'>model_class</span><span class='period'>.</span><span class='id identifier rubyid_scope'>scope</span><span class='lparen'>(</span><span class='symbol'>:&quot;with_any_</span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_attribute_name'>attribute_name</span><span class='embexpr_end'>}</span><span class='tstring_end'>&quot;</span></span><span class='comma'>,</span> <span class='id identifier rubyid_lambda'>lambda</span> <span class='kw'>do</span> <span class='op'>|</span><span class='op'>*</span><span class='id identifier rubyid_keys'>keys</span><span class='op'>|</span>
923
+ <span class='id identifier rubyid_keys'>keys</span> <span class='op'>=</span> <span class='const'><span class='object_link'><a href="../Anchormodel.html" title="Anchormodel (class)">Anchormodel</a></span></span><span class='op'>::</span><span class='const'><span class='object_link'><a href="" title="Anchormodel::Util (module)">Util</a></span></span><span class='period'>.</span><span class='id identifier rubyid_normalize_anchormodel_keys'><span class='object_link'><a href="#normalize_anchormodel_keys-class_method" title="Anchormodel::Util.normalize_anchormodel_keys (method)">normalize_anchormodel_keys</a></span></span><span class='lparen'>(</span><span class='id identifier rubyid_keys'>keys</span><span class='comma'>,</span> <span class='id identifier rubyid_anchormodel_class'>anchormodel_class</span><span class='rparen'>)</span>
924
+ <span class='kw'>next</span> <span class='id identifier rubyid_none'>none</span> <span class='kw'>if</span> <span class='id identifier rubyid_keys'>keys</span><span class='period'>.</span><span class='id identifier rubyid_empty?'>empty?</span>
925
+
926
+ <span class='id identifier rubyid_clauses'>clauses</span> <span class='op'>=</span> <span class='id identifier rubyid_keys'>keys</span><span class='period'>.</span><span class='id identifier rubyid_map'>map</span> <span class='lbrace'>{</span> <span class='op'>|</span><span class='id identifier rubyid_k'>k</span><span class='op'>|</span> <span class='const'><span class='object_link'><a href="../Anchormodel.html" title="Anchormodel (class)">Anchormodel</a></span></span><span class='op'>::</span><span class='const'><span class='object_link'><a href="" title="Anchormodel::Util (module)">Util</a></span></span><span class='period'>.</span><span class='id identifier rubyid_csv_contains_like'><span class='object_link'><a href="#csv_contains_like-class_method" title="Anchormodel::Util.csv_contains_like (method)">csv_contains_like</a></span></span><span class='lparen'>(</span><span class='id identifier rubyid_attribute_name'>attribute_name</span><span class='comma'>,</span> <span class='id identifier rubyid_k'>k</span><span class='rparen'>)</span> <span class='rbrace'>}</span>
927
+ <span class='id identifier rubyid_sql'>sql</span> <span class='op'>=</span> <span class='id identifier rubyid_clauses'>clauses</span><span class='period'>.</span><span class='id identifier rubyid_map'>map</span> <span class='lbrace'>{</span> <span class='op'>|</span><span class='id identifier rubyid_c'>c</span><span class='op'>|</span> <span class='tstring'><span class='tstring_beg'>&quot;</span><span class='tstring_content'>(</span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_c'>c</span><span class='period'>.</span><span class='id identifier rubyid_first'>first</span><span class='embexpr_end'>}</span><span class='tstring_content'>)</span><span class='tstring_end'>&quot;</span></span> <span class='rbrace'>}</span><span class='period'>.</span><span class='id identifier rubyid_join'>join</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'> OR </span><span class='tstring_end'>&#39;</span></span><span class='rparen'>)</span>
928
+ <span class='id identifier rubyid_binds'>binds</span> <span class='op'>=</span> <span class='id identifier rubyid_clauses'>clauses</span><span class='period'>.</span><span class='id identifier rubyid_flat_map'>flat_map</span> <span class='lbrace'>{</span> <span class='op'>|</span><span class='id identifier rubyid_c'>c</span><span class='op'>|</span> <span class='id identifier rubyid_c'>c</span><span class='period'>.</span><span class='id identifier rubyid_drop'>drop</span><span class='lparen'>(</span><span class='int'>1</span><span class='rparen'>)</span> <span class='rbrace'>}</span>
929
+ <span class='id identifier rubyid_where'>where</span><span class='lparen'>(</span><span class='id identifier rubyid_sql'>sql</span><span class='comma'>,</span> <span class='op'>*</span><span class='id identifier rubyid_binds'>binds</span><span class='rparen'>)</span>
930
+ <span class='kw'>end</span><span class='rparen'>)</span>
931
+
932
+ <span class='id identifier rubyid_model_class'>model_class</span><span class='period'>.</span><span class='id identifier rubyid_scope'>scope</span><span class='lparen'>(</span><span class='symbol'>:&quot;with_all_</span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_attribute_name'>attribute_name</span><span class='embexpr_end'>}</span><span class='tstring_end'>&quot;</span></span><span class='comma'>,</span> <span class='id identifier rubyid_lambda'>lambda</span> <span class='kw'>do</span> <span class='op'>|</span><span class='op'>*</span><span class='id identifier rubyid_keys'>keys</span><span class='op'>|</span>
933
+ <span class='id identifier rubyid_keys'>keys</span> <span class='op'>=</span> <span class='const'><span class='object_link'><a href="../Anchormodel.html" title="Anchormodel (class)">Anchormodel</a></span></span><span class='op'>::</span><span class='const'><span class='object_link'><a href="" title="Anchormodel::Util (module)">Util</a></span></span><span class='period'>.</span><span class='id identifier rubyid_normalize_anchormodel_keys'><span class='object_link'><a href="#normalize_anchormodel_keys-class_method" title="Anchormodel::Util.normalize_anchormodel_keys (method)">normalize_anchormodel_keys</a></span></span><span class='lparen'>(</span><span class='id identifier rubyid_keys'>keys</span><span class='comma'>,</span> <span class='id identifier rubyid_anchormodel_class'>anchormodel_class</span><span class='rparen'>)</span>
934
+ <span class='kw'>next</span> <span class='id identifier rubyid_all'>all</span> <span class='kw'>if</span> <span class='id identifier rubyid_keys'>keys</span><span class='period'>.</span><span class='id identifier rubyid_empty?'>empty?</span>
935
+
936
+ <span class='id identifier rubyid_keys'>keys</span><span class='period'>.</span><span class='id identifier rubyid_reduce'>reduce</span><span class='lparen'>(</span><span class='id identifier rubyid_all'>all</span><span class='rparen'>)</span> <span class='lbrace'>{</span> <span class='op'>|</span><span class='id identifier rubyid_rel'>rel</span><span class='comma'>,</span> <span class='id identifier rubyid_k'>k</span><span class='op'>|</span> <span class='id identifier rubyid_rel'>rel</span><span class='period'>.</span><span class='id identifier rubyid_merge'>merge</span><span class='lparen'>(</span><span class='id identifier rubyid_public_send'>public_send</span><span class='lparen'>(</span><span class='symbol'>:&quot;with_any_</span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_attribute_name'>attribute_name</span><span class='embexpr_end'>}</span><span class='tstring_end'>&quot;</span></span><span class='comma'>,</span> <span class='id identifier rubyid_k'>k</span><span class='rparen'>)</span><span class='rparen'>)</span> <span class='rbrace'>}</span>
937
+ <span class='kw'>end</span><span class='rparen'>)</span>
938
+ <span class='kw'>end</span>
939
+ <span class='kw'>end</span></pre>
940
+ </td>
941
+ </tr>
942
+ </table>
943
+ </div>
944
+
945
+ <div class="method_details ">
946
+ <h3 class="signature " id="normalize_anchormodel_keys-class_method">
947
+
948
+ .<strong>normalize_anchormodel_keys</strong>(keys, anchormodel_class) &#x21d2; <tt>Array&lt;String&gt;</tt>
949
+
950
+
951
+
952
+
953
+
954
+ </h3><div class="docstring">
955
+ <div class="discussion">
956
+
957
+ <p>Coerces a list of mixed-type key inputs into validated key Strings, ready for SQL binding. Accepts Strings, Symbols, Anchormodel instances, and arbitrarily nested arrays of those.</p>
958
+
959
+
960
+ </div>
961
+ </div>
962
+ <div class="tags">
963
+
964
+ <div class="examples">
965
+ <p class="tag_title">Examples:</p>
966
+
967
+
968
+ <pre class="example code"><code><span class='const'><span class='object_link'><a href="../Anchormodel.html" title="Anchormodel (class)">Anchormodel</a></span></span><span class='op'>::</span><span class='const'><span class='object_link'><a href="" title="Anchormodel::Util (module)">Util</a></span></span><span class='period'>.</span><span class='id identifier rubyid_normalize_anchormodel_keys'>normalize_anchormodel_keys</span><span class='lparen'>(</span><span class='lbracket'>[</span><span class='symbol'>:cat</span><span class='comma'>,</span> <span class='tstring'><span class='tstring_beg'>&#39;</span><span class='tstring_content'>dog</span><span class='tstring_end'>&#39;</span></span><span class='comma'>,</span> <span class='const'>Animal</span><span class='period'>.</span><span class='id identifier rubyid_find'>find</span><span class='lparen'>(</span><span class='symbol'>:horse</span><span class='rparen'>)</span><span class='rbracket'>]</span><span class='comma'>,</span> <span class='const'>Animal</span><span class='rparen'>)</span>
969
+ <span class='comment'># =&gt; [&quot;cat&quot;, &quot;dog&quot;, &quot;horse&quot;]</span></code></pre>
970
+
971
+ </div>
972
+ <p class="tag_title">Parameters:</p>
973
+ <ul class="param">
974
+
975
+ <li>
976
+
977
+ <span class='name'>keys</span>
978
+
979
+
980
+ <span class='type'>(<tt>Array</tt>)</span>
981
+
982
+
983
+
984
+ &mdash;
985
+ <div class='inline'>
986
+ <p>Input list (flattened internally).</p>
987
+ </div>
988
+
989
+ </li>
990
+
991
+ <li>
992
+
993
+ <span class='name'>anchormodel_class</span>
994
+
995
+
996
+ <span class='type'>(<tt>Class</tt>)</span>
997
+
998
+
999
+
1000
+ &mdash;
1001
+ <div class='inline'>
1002
+ <p>The anchormodel class against which keys are validated.</p>
1003
+ </div>
1004
+
1005
+ </li>
1006
+
1007
+ </ul>
1008
+
1009
+ <p class="tag_title">Returns:</p>
1010
+ <ul class="return">
1011
+
1012
+ <li>
1013
+
1014
+
1015
+ <span class='type'>(<tt>Array&lt;String&gt;</tt>)</span>
1016
+
1017
+
1018
+
1019
+ &mdash;
1020
+ <div class='inline'>
1021
+ <p>Flattened, stringified, validated keys.</p>
1022
+ </div>
1023
+
1024
+ </li>
1025
+
1026
+ </ul>
1027
+ <p class="tag_title">Raises:</p>
1028
+ <ul class="raise">
1029
+
1030
+ <li>
1031
+
1032
+
1033
+ <span class='type'>(<tt><span class='object_link'><a href="InvalidKey.html" title="Anchormodel::InvalidKey (class)">Anchormodel::InvalidKey</a></span></tt>)</span>
1034
+
1035
+
1036
+
1037
+ &mdash;
1038
+ <div class='inline'>
1039
+ <p>if any element is not a registered key.</p>
1040
+ </div>
1041
+
1042
+ </li>
1043
+
1044
+ </ul>
1045
+
1046
+ </div><table class="source_code">
1047
+ <tr>
1048
+ <td>
1049
+ <pre class="lines">
1050
+
1051
+
1052
+ 193
1053
+ 194
1054
+ 195
1055
+ 196
1056
+ 197</pre>
1057
+ </td>
1058
+ <td>
1059
+ <pre class="code"><span class="info file"># File 'lib/anchormodel/util.rb', line 193</span>
1060
+
1061
+ <span class='kw'>def</span> <span class='kw'>self</span><span class='period'>.</span><span class='id identifier rubyid_normalize_anchormodel_keys'>normalize_anchormodel_keys</span><span class='lparen'>(</span><span class='id identifier rubyid_keys'>keys</span><span class='comma'>,</span> <span class='id identifier rubyid_anchormodel_class'>anchormodel_class</span><span class='rparen'>)</span>
1062
+ <span class='id identifier rubyid_keys'>keys</span> <span class='op'>=</span> <span class='id identifier rubyid_keys'>keys</span><span class='period'>.</span><span class='id identifier rubyid_flatten'>flatten</span><span class='period'>.</span><span class='id identifier rubyid_map'>map</span> <span class='lbrace'>{</span> <span class='op'>|</span><span class='id identifier rubyid_k'>k</span><span class='op'>|</span> <span class='id identifier rubyid_k'>k</span><span class='period'>.</span><span class='id identifier rubyid_respond_to?'>respond_to?</span><span class='lparen'>(</span><span class='symbol'>:key</span><span class='rparen'>)</span> <span class='op'>?</span> <span class='id identifier rubyid_k'>k</span><span class='period'>.</span><span class='id identifier rubyid_key'>key</span><span class='period'>.</span><span class='id identifier rubyid_to_s'>to_s</span> <span class='op'>:</span> <span class='id identifier rubyid_k'>k</span><span class='period'>.</span><span class='id identifier rubyid_to_s'>to_s</span> <span class='rbrace'>}</span>
1063
+ <span class='id identifier rubyid_keys'>keys</span><span class='period'>.</span><span class='id identifier rubyid_each'>each</span> <span class='lbrace'>{</span> <span class='op'>|</span><span class='id identifier rubyid_k'>k</span><span class='op'>|</span> <span class='id identifier rubyid_anchormodel_class'>anchormodel_class</span><span class='period'>.</span><span class='id identifier rubyid_find'>find</span><span class='lparen'>(</span><span class='id identifier rubyid_k'>k</span><span class='rparen'>)</span> <span class='rbrace'>}</span>
1064
+ <span class='id identifier rubyid_keys'>keys</span>
606
1065
  <span class='kw'>end</span></pre>
607
1066
  </td>
608
1067
  </tr>
@@ -614,7 +1073,7 @@
614
1073
  </div>
615
1074
 
616
1075
  <div id="footer">
617
- Generated on Wed May 13 11:46:10 2026 by
1076
+ Generated on Wed May 13 15:48:24 2026 by
618
1077
  <a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
619
1078
  0.9.28 (ruby-3.3.5).
620
1079
  </div>