anchormodel 0.0.2 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.ruby-version +1 -1
- data/CHANGELOG.md +11 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +206 -0
- data/README.md +98 -9
- data/Rakefile +23 -3
- data/anchormodel.gemspec +26 -10
- data/bin/rails +7 -0
- data/doc/Anchormodel/ActiveModelTypeValue.html +14 -10
- data/doc/Anchormodel/Attribute.html +75 -71
- data/doc/Anchormodel/ModelMixin.html +190 -21
- data/doc/Anchormodel/Version.html +4 -4
- data/doc/Anchormodel.html +151 -53
- data/doc/_index.html +2 -2
- data/doc/file.README.html +118 -47
- data/doc/index.html +118 -47
- data/doc/method_list.html +9 -1
- data/doc/top-level-namespace.html +2 -2
- data/lib/anchormodel/active_model_type_value.rb +4 -4
- data/lib/anchormodel/attribute.rb +4 -9
- data/lib/anchormodel/model_mixin.rb +53 -3
- data/lib/anchormodel/version.rb +2 -2
- data/lib/anchormodel.rb +7 -2
- data/logo.svg +98 -0
- data/test/active_record_model/user_test.rb +115 -0
- data/test/dummy/.gitignore +29 -0
- data/test/dummy/Rakefile +6 -0
- data/test/dummy/app/anchormodels/locale.rb +6 -0
- data/test/dummy/app/anchormodels/role.rb +14 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/models/application_record.rb +5 -0
- data/test/dummy/app/models/concerns/.keep +0 -0
- data/test/dummy/app/models/user.rb +6 -0
- data/test/dummy/bin/rails +4 -0
- data/test/dummy/bin/rake +4 -0
- data/test/dummy/bin/setup +33 -0
- data/test/dummy/config/application.rb +37 -0
- data/test/dummy/config/boot.rb +3 -0
- data/test/dummy/config/credentials.yml.enc +1 -0
- data/test/dummy/config/database.yml +8 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/test.rb +50 -0
- data/test/dummy/config/initializers/content_security_policy.rb +25 -0
- data/test/dummy/config/initializers/filter_parameter_logging.rb +8 -0
- data/test/dummy/config/initializers/inflections.rb +16 -0
- data/test/dummy/config/initializers/permissions_policy.rb +11 -0
- data/test/dummy/config/locales/en.yml +33 -0
- data/test/dummy/config/puma.rb +43 -0
- data/test/dummy/config/routes.rb +6 -0
- data/test/dummy/config.ru +6 -0
- data/test/dummy/db/migrate/20230107173151_create_users.rb +12 -0
- data/test/dummy/db/schema.rb +23 -0
- data/test/dummy/db/seeds.rb +7 -0
- data/test/dummy/lib/tasks/.keep +0 -0
- data/test/dummy/log/.keep +0 -0
- data/test/dummy/tmp/.keep +0 -0
- data/test/dummy/tmp/pids/.keep +0 -0
- data/test/test_helper.rb +21 -0
- metadata +149 -13
- data/anchormodel-0.0.1.gem +0 -0
data/doc/Anchormodel.html
CHANGED
@@ -103,8 +103,8 @@
|
|
103
103
|
|
104
104
|
<h2>Overview</h2><div class="docstring">
|
105
105
|
<div class="discussion">
|
106
|
-
|
107
|
-
Refer to the README for usage.</p>
|
106
|
+
|
107
|
+
<p>Inherit from this class and place your Anchormodel under <code>app/anchormodels/your_anchor_model.rb</code>. Use it like <code>YourAnchorModel</code>. Refer to the README for usage.</p>
|
108
108
|
|
109
109
|
|
110
110
|
</div>
|
@@ -215,7 +215,8 @@ Refer to the README for usage.</p>
|
|
215
215
|
|
216
216
|
|
217
217
|
|
218
|
-
<span class="summary_desc"><div class='inline'
|
218
|
+
<span class="summary_desc"><div class='inline'>
|
219
|
+
<p>Returns all possible values this Anchormodel can take.</p>
|
219
220
|
</div></span>
|
220
221
|
|
221
222
|
</li>
|
@@ -238,7 +239,32 @@ Refer to the README for usage.</p>
|
|
238
239
|
|
239
240
|
|
240
241
|
|
241
|
-
<span class="summary_desc"><div class='inline'
|
242
|
+
<span class="summary_desc"><div class='inline'>
|
243
|
+
<p>Retrieves a particular value given the key.</p>
|
244
|
+
</div></span>
|
245
|
+
|
246
|
+
</li>
|
247
|
+
|
248
|
+
|
249
|
+
<li class="public ">
|
250
|
+
<span class="summary_signature">
|
251
|
+
|
252
|
+
<a href="#setup!-class_method" title="setup! (class method)">.<strong>setup!</strong> ⇒ Object </a>
|
253
|
+
|
254
|
+
|
255
|
+
|
256
|
+
</span>
|
257
|
+
|
258
|
+
|
259
|
+
|
260
|
+
|
261
|
+
|
262
|
+
|
263
|
+
|
264
|
+
|
265
|
+
|
266
|
+
<span class="summary_desc"><div class='inline'>
|
267
|
+
<p>When a descendant of Anchormodel is first used, it must overwrite the class_attributes to prevent cross-class pollution.</p>
|
242
268
|
</div></span>
|
243
269
|
|
244
270
|
</li>
|
@@ -294,7 +320,8 @@ Refer to the README for usage.</p>
|
|
294
320
|
|
295
321
|
|
296
322
|
|
297
|
-
<span class="summary_desc"><div class='inline'
|
323
|
+
<span class="summary_desc"><div class='inline'>
|
324
|
+
<p>Call this initializer directly in your Anchormodel class.</p>
|
298
325
|
</div></span>
|
299
326
|
|
300
327
|
</li>
|
@@ -339,7 +366,8 @@ Refer to the README for usage.</p>
|
|
339
366
|
|
340
367
|
|
341
368
|
|
342
|
-
<span class="summary_desc"><div class='inline'
|
369
|
+
<span class="summary_desc"><div class='inline'>
|
370
|
+
<p>Returns a Rails label that is compatible with the <a href="https://github.com/grosser/gettext_i18n_rails/">Rails FastGettext</a> gem.</p>
|
343
371
|
</div></span>
|
344
372
|
|
345
373
|
</li>
|
@@ -384,7 +412,8 @@ Refer to the README for usage.</p>
|
|
384
412
|
|
385
413
|
</h3><div class="docstring">
|
386
414
|
<div class="discussion">
|
387
|
-
|
415
|
+
|
416
|
+
<p>Call this initializer directly in your Anchormodel class. To set <code>@foo=:bar</code> for anchor <code>:ter</code>, use <code>new(:ter, foo: :bar)</code></p>
|
388
417
|
|
389
418
|
|
390
419
|
</div>
|
@@ -403,7 +432,8 @@ Refer to the README for usage.</p>
|
|
403
432
|
|
404
433
|
|
405
434
|
—
|
406
|
-
<div class='inline'
|
435
|
+
<div class='inline'>
|
436
|
+
<p>The key under which the entry should be stored.</p>
|
407
437
|
</div>
|
408
438
|
|
409
439
|
</li>
|
@@ -418,7 +448,8 @@ Refer to the README for usage.</p>
|
|
418
448
|
|
419
449
|
|
420
450
|
—
|
421
|
-
<div class='inline'
|
451
|
+
<div class='inline'>
|
452
|
+
<p>All named arguments to Anchormodel are made available as instance attributes.</p>
|
422
453
|
</div>
|
423
454
|
|
424
455
|
</li>
|
@@ -432,27 +463,36 @@ Refer to the README for usage.</p>
|
|
432
463
|
<pre class="lines">
|
433
464
|
|
434
465
|
|
435
|
-
27
|
436
|
-
28
|
437
|
-
29
|
438
|
-
30
|
439
|
-
31
|
440
|
-
32
|
441
|
-
33
|
442
|
-
34
|
443
|
-
35
|
444
|
-
36
|
445
|
-
37
|
446
466
|
38
|
447
467
|
39
|
448
468
|
40
|
449
469
|
41
|
450
|
-
42
|
470
|
+
42
|
471
|
+
43
|
472
|
+
44
|
473
|
+
45
|
474
|
+
46
|
475
|
+
47
|
476
|
+
48
|
477
|
+
49
|
478
|
+
50
|
479
|
+
51
|
480
|
+
52
|
481
|
+
53
|
482
|
+
54
|
483
|
+
55
|
484
|
+
56
|
485
|
+
57
|
486
|
+
58
|
487
|
+
59
|
488
|
+
60</pre>
|
451
489
|
</td>
|
452
490
|
<td>
|
453
|
-
<pre class="code"><span class="info file"># File 'lib/anchormodel.rb', line
|
491
|
+
<pre class="code"><span class="info file"># File 'lib/anchormodel.rb', line 38</span>
|
454
492
|
|
455
493
|
<span class='kw'>def</span> <span class='id identifier rubyid_initialize'>initialize</span><span class='lparen'>(</span><span class='id identifier rubyid_key'>key</span><span class='comma'>,</span> <span class='op'>**</span><span class='id identifier rubyid_attributes'>attributes</span><span class='rparen'>)</span>
|
494
|
+
<span class='kw'>self</span><span class='period'>.</span><span class='id identifier rubyid_class'>class</span><span class='period'>.</span><span class='id identifier rubyid_setup!'>setup!</span> <span class='kw'>unless</span> <span class='kw'>self</span><span class='period'>.</span><span class='id identifier rubyid_class'>class</span><span class='period'>.</span><span class='id identifier rubyid_setup_completed'>setup_completed</span>
|
495
|
+
|
456
496
|
<span class='ivar'>@key</span> <span class='op'>=</span> <span class='id identifier rubyid_key'>key</span><span class='period'>.</span><span class='id identifier rubyid_to_sym'>to_sym</span>
|
457
497
|
<span class='ivar'>@index</span> <span class='op'>=</span> <span class='id identifier rubyid_entries_list'>entries_list</span><span class='period'>.</span><span class='id identifier rubyid_count'>count</span>
|
458
498
|
|
@@ -467,6 +507,11 @@ Refer to the README for usage.</p>
|
|
467
507
|
|
468
508
|
<span class='comment'># Register valid keys
|
469
509
|
</span> <span class='id identifier rubyid_valid_keys'>valid_keys</span> <span class='op'><<</span> <span class='id identifier rubyid_key'>key</span>
|
510
|
+
|
511
|
+
<span class='comment'># Define boolean reader
|
512
|
+
</span> <span class='kw'>self</span><span class='period'>.</span><span class='id identifier rubyid_class'>class</span><span class='period'>.</span><span class='id identifier rubyid_define_method'>define_method</span><span class='lparen'>(</span><span class='symbol'>:"#{</span><span class='id identifier rubyid_key'>key</span><span class='embexpr_end'>}</span><span class='tstring_content'>?</span><span class='tstring_end'>"</span></span><span class='rparen'>)</span> <span class='kw'>do</span>
|
513
|
+
<span class='ivar'>@key</span> <span class='op'>==</span> <span class='id identifier rubyid_key'>key</span>
|
514
|
+
<span class='kw'>end</span>
|
470
515
|
<span class='kw'>end</span></pre>
|
471
516
|
</td>
|
472
517
|
</tr>
|
@@ -578,7 +623,8 @@ Refer to the README for usage.</p>
|
|
578
623
|
|
579
624
|
</h3><div class="docstring">
|
580
625
|
<div class="discussion">
|
581
|
-
|
626
|
+
|
627
|
+
<p>Returns all possible values this Anchormodel can take.</p>
|
582
628
|
|
583
629
|
|
584
630
|
</div>
|
@@ -592,12 +638,12 @@ Refer to the README for usage.</p>
|
|
592
638
|
<pre class="lines">
|
593
639
|
|
594
640
|
|
595
|
-
|
596
|
-
|
597
|
-
|
641
|
+
24
|
642
|
+
25
|
643
|
+
26</pre>
|
598
644
|
</td>
|
599
645
|
<td>
|
600
|
-
<pre class="code"><span class="info file"># File 'lib/anchormodel.rb', line
|
646
|
+
<pre class="code"><span class="info file"># File 'lib/anchormodel.rb', line 24</span>
|
601
647
|
|
602
648
|
<span class='kw'>def</span> <span class='kw'>self</span><span class='period'>.</span><span class='id identifier rubyid_all'>all</span>
|
603
649
|
<span class='id identifier rubyid_entries_list'>entries_list</span>
|
@@ -618,7 +664,8 @@ Refer to the README for usage.</p>
|
|
618
664
|
|
619
665
|
</h3><div class="docstring">
|
620
666
|
<div class="discussion">
|
621
|
-
|
667
|
+
|
668
|
+
<p>Retrieves a particular value given the key. Fails if not found.</p>
|
622
669
|
|
623
670
|
|
624
671
|
</div>
|
@@ -637,7 +684,8 @@ Refer to the README for usage.</p>
|
|
637
684
|
|
638
685
|
|
639
686
|
—
|
640
|
-
<div class='inline'
|
687
|
+
<div class='inline'>
|
688
|
+
<p>The key of the value that should be retrieved.</p>
|
641
689
|
</div>
|
642
690
|
|
643
691
|
</li>
|
@@ -651,13 +699,13 @@ Refer to the README for usage.</p>
|
|
651
699
|
<pre class="lines">
|
652
700
|
|
653
701
|
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
702
|
+
30
|
703
|
+
31
|
704
|
+
32
|
705
|
+
33</pre>
|
658
706
|
</td>
|
659
707
|
<td>
|
660
|
-
<pre class="code"><span class="info file"># File 'lib/anchormodel.rb', line
|
708
|
+
<pre class="code"><span class="info file"># File 'lib/anchormodel.rb', line 30</span>
|
661
709
|
|
662
710
|
<span class='kw'>def</span> <span class='kw'>self</span><span class='period'>.</span><span class='id identifier rubyid_find'>find</span><span class='lparen'>(</span><span class='id identifier rubyid_key'>key</span><span class='rparen'>)</span>
|
663
711
|
<span class='kw'>return</span> <span class='kw'>nil</span> <span class='kw'>if</span> <span class='id identifier rubyid_key'>key</span><span class='period'>.</span><span class='id identifier rubyid_nil?'>nil?</span>
|
@@ -666,6 +714,55 @@ Refer to the README for usage.</p>
|
|
666
714
|
</td>
|
667
715
|
</tr>
|
668
716
|
</table>
|
717
|
+
</div>
|
718
|
+
|
719
|
+
<div class="method_details ">
|
720
|
+
<h3 class="signature " id="setup!-class_method">
|
721
|
+
|
722
|
+
.<strong>setup!</strong> ⇒ <tt>Object</tt>
|
723
|
+
|
724
|
+
|
725
|
+
|
726
|
+
|
727
|
+
|
728
|
+
</h3><div class="docstring">
|
729
|
+
<div class="discussion">
|
730
|
+
|
731
|
+
<p>When a descendant of Anchormodel is first used, it must overwrite the class_attributes to prevent cross-class pollution.</p>
|
732
|
+
|
733
|
+
|
734
|
+
</div>
|
735
|
+
</div>
|
736
|
+
<div class="tags">
|
737
|
+
|
738
|
+
|
739
|
+
</div><table class="source_code">
|
740
|
+
<tr>
|
741
|
+
<td>
|
742
|
+
<pre class="lines">
|
743
|
+
|
744
|
+
|
745
|
+
15
|
746
|
+
16
|
747
|
+
17
|
748
|
+
18
|
749
|
+
19
|
750
|
+
20
|
751
|
+
21</pre>
|
752
|
+
</td>
|
753
|
+
<td>
|
754
|
+
<pre class="code"><span class="info file"># File 'lib/anchormodel.rb', line 15</span>
|
755
|
+
|
756
|
+
<span class='kw'>def</span> <span class='kw'>self</span><span class='period'>.</span><span class='id identifier rubyid_setup!'>setup!</span>
|
757
|
+
<span class='id identifier rubyid_fail'>fail</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>"</span><span class='tstring_content'>`setup!` was called twice for Anchormodel subclass </span><span class='embexpr_beg'>#{</span><span class='kw'>self</span><span class='embexpr_end'>}</span><span class='tstring_content'>.</span><span class='tstring_end'>"</span></span><span class='rparen'>)</span> <span class='kw'>if</span> <span class='id identifier rubyid_setup_completed'>setup_completed</span>
|
758
|
+
<span class='kw'>self</span><span class='period'>.</span><span class='id identifier rubyid_entries_list'>entries_list</span> <span class='op'>=</span> <span class='id identifier rubyid_entries_list'>entries_list</span><span class='period'>.</span><span class='id identifier rubyid_dup'>dup</span>
|
759
|
+
<span class='kw'>self</span><span class='period'>.</span><span class='id identifier rubyid_entries_hash'>entries_hash</span> <span class='op'>=</span> <span class='id identifier rubyid_entries_hash'>entries_hash</span><span class='period'>.</span><span class='id identifier rubyid_dup'>dup</span>
|
760
|
+
<span class='kw'>self</span><span class='period'>.</span><span class='id identifier rubyid_valid_keys'>valid_keys</span> <span class='op'>=</span> <span class='id identifier rubyid_valid_keys'>valid_keys</span><span class='period'>.</span><span class='id identifier rubyid_dup'>dup</span>
|
761
|
+
<span class='kw'>self</span><span class='period'>.</span><span class='id identifier rubyid_setup_completed'>setup_completed</span> <span class='op'>=</span> <span class='kw'>true</span>
|
762
|
+
<span class='kw'>end</span></pre>
|
763
|
+
</td>
|
764
|
+
</tr>
|
765
|
+
</table>
|
669
766
|
</div>
|
670
767
|
|
671
768
|
</div>
|
@@ -698,12 +795,12 @@ Refer to the README for usage.</p>
|
|
698
795
|
<pre class="lines">
|
699
796
|
|
700
797
|
|
701
|
-
|
702
|
-
|
703
|
-
|
798
|
+
62
|
799
|
+
63
|
800
|
+
64</pre>
|
704
801
|
</td>
|
705
802
|
<td>
|
706
|
-
<pre class="code"><span class="info file"># File 'lib/anchormodel.rb', line
|
803
|
+
<pre class="code"><span class="info file"># File 'lib/anchormodel.rb', line 62</span>
|
707
804
|
|
708
805
|
<span class='kw'>def</span> <span class='op'>==</span><span class='lparen'>(</span><span class='id identifier rubyid_other'>other</span><span class='rparen'>)</span>
|
709
806
|
<span class='kw'>self</span><span class='period'>.</span><span class='id identifier rubyid_class'>class</span> <span class='op'>==</span> <span class='id identifier rubyid_other'>other</span><span class='period'>.</span><span class='id identifier rubyid_class'>class</span> <span class='op'>&&</span> <span class='id identifier rubyid_key'>key</span> <span class='op'>==</span> <span class='id identifier rubyid_other'>other</span><span class='period'>.</span><span class='id identifier rubyid_key'>key</span>
|
@@ -737,12 +834,12 @@ Refer to the README for usage.</p>
|
|
737
834
|
<pre class="lines">
|
738
835
|
|
739
836
|
|
740
|
-
|
741
|
-
|
742
|
-
|
837
|
+
71
|
838
|
+
72
|
839
|
+
73</pre>
|
743
840
|
</td>
|
744
841
|
<td>
|
745
|
-
<pre class="code"><span class="info file"># File 'lib/anchormodel.rb', line
|
842
|
+
<pre class="code"><span class="info file"># File 'lib/anchormodel.rb', line 71</span>
|
746
843
|
|
747
844
|
<span class='kw'>def</span> <span class='id identifier rubyid_inspect'>inspect</span>
|
748
845
|
<span class='tstring'><span class='tstring_beg'>"</span><span class='tstring_content'>#<</span><span class='embexpr_beg'>#{</span><span class='kw'>self</span><span class='period'>.</span><span class='id identifier rubyid_class'>class</span><span class='period'>.</span><span class='id identifier rubyid_name'>name</span><span class='embexpr_end'>}</span><span class='tstring_content'><</span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_key'>key</span><span class='embexpr_end'>}</span><span class='tstring_content'>>:</span><span class='embexpr_beg'>#{</span><span class='id identifier rubyid_hash'>hash</span><span class='embexpr_end'>}</span><span class='tstring_content'>></span><span class='tstring_end'>"</span></span>
|
@@ -763,7 +860,8 @@ Refer to the README for usage.</p>
|
|
763
860
|
|
764
861
|
</h3><div class="docstring">
|
765
862
|
<div class="discussion">
|
766
|
-
|
863
|
+
|
864
|
+
<p>Returns a Rails label that is compatible with the <a href="https://github.com/grosser/gettext_i18n_rails/">Rails FastGettext</a> gem.</p>
|
767
865
|
|
768
866
|
|
769
867
|
</div>
|
@@ -777,12 +875,12 @@ Refer to the README for usage.</p>
|
|
777
875
|
<pre class="lines">
|
778
876
|
|
779
877
|
|
780
|
-
|
781
|
-
|
782
|
-
|
878
|
+
67
|
879
|
+
68
|
880
|
+
69</pre>
|
783
881
|
</td>
|
784
882
|
<td>
|
785
|
-
<pre class="code"><span class="info file"># File 'lib/anchormodel.rb', line
|
883
|
+
<pre class="code"><span class="info file"># File 'lib/anchormodel.rb', line 67</span>
|
786
884
|
|
787
885
|
<span class='kw'>def</span> <span class='id identifier rubyid_label'>label</span>
|
788
886
|
<span class='const'>I18n</span><span class='period'>.</span><span class='id identifier rubyid_t'>t</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>"</span><span class='embexpr_beg'>#{</span><span class='kw'>self</span><span class='period'>.</span><span class='id identifier rubyid_class'>class</span><span class='period'>.</span><span class='id identifier rubyid_name'>name</span><span class='period'>.</span><span class='id identifier rubyid_demodulize'>demodulize</span><span class='embexpr_end'>}</span><span class='tstring_content'>|</span><span class='embexpr_beg'>#{</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='period'>.</span><span class='id identifier rubyid_humanize'>humanize</span><span class='embexpr_end'>}</span><span class='tstring_end'>"</span></span><span class='rparen'>)</span>
|
@@ -816,12 +914,12 @@ Refer to the README for usage.</p>
|
|
816
914
|
<pre class="lines">
|
817
915
|
|
818
916
|
|
819
|
-
|
820
|
-
|
821
|
-
|
917
|
+
75
|
918
|
+
76
|
919
|
+
77</pre>
|
822
920
|
</td>
|
823
921
|
<td>
|
824
|
-
<pre class="code"><span class="info file"># File 'lib/anchormodel.rb', line
|
922
|
+
<pre class="code"><span class="info file"># File 'lib/anchormodel.rb', line 75</span>
|
825
923
|
|
826
924
|
<span class='kw'>def</span> <span class='id identifier rubyid_to_s'>to_s</span>
|
827
925
|
<span class='id identifier rubyid_inspect'>inspect</span>
|
@@ -836,9 +934,9 @@ Refer to the README for usage.</p>
|
|
836
934
|
</div>
|
837
935
|
|
838
936
|
<div id="footer">
|
839
|
-
Generated on
|
937
|
+
Generated on Tue Jan 24 20:27:59 2023 by
|
840
938
|
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
841
|
-
0.9.28 (ruby-3.
|
939
|
+
0.9.28 (ruby-3.1.3).
|
842
940
|
</div>
|
843
941
|
|
844
942
|
</div>
|
data/doc/_index.html
CHANGED
@@ -141,9 +141,9 @@
|
|
141
141
|
</div>
|
142
142
|
|
143
143
|
<div id="footer">
|
144
|
-
Generated on
|
144
|
+
Generated on Tue Jan 24 20:27:58 2023 by
|
145
145
|
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
146
|
-
0.9.28 (ruby-3.
|
146
|
+
0.9.28 (ruby-3.1.3).
|
147
147
|
</div>
|
148
148
|
|
149
149
|
</div>
|
data/doc/file.README.html
CHANGED
@@ -57,63 +57,59 @@
|
|
57
57
|
<div class="clear"></div>
|
58
58
|
</div>
|
59
59
|
|
60
|
-
<div id="content"><div id='filecontents'
|
60
|
+
<div id="content"><div id='filecontents'>
|
61
|
+
<p><img src=“logo.svg” height=250 alt=“Anchormodel logo”/></p>
|
61
62
|
|
62
|
-
<
|
63
|
-
Enums</a>. In
|
64
|
-
contrast to regular Enums, Anchormodels can hold application logic, making them
|
65
|
-
ideal for tying code to database objects.</p>
|
63
|
+
<h1 id="label-Introducing+Anchormodel">Introducing Anchormodel</h1>
|
66
64
|
|
67
|
-
<
|
65
|
+
<p>This gem provides a simple but powerful alternative to <a href="https://api.rubyonrails.org/v7.0/classes/ActiveRecord/Enum.html">Rails Enums</a>. In contrast to regular Enums, Anchormodels can hold application logic, making them ideal for tying code to database objects.</p>
|
66
|
+
|
67
|
+
<h1 id="label-Use+case">Use case</h1>
|
68
68
|
|
69
69
|
<p>Typically, a Rails application consists of three kinds of state:</p>
|
70
|
+
<ul><li>
|
71
|
+
<p>The code, which we can consider static within a given version. Code can reference to other code, e.g. <code>node.parent = other_node</code>.</p>
|
72
|
+
</li><li>
|
73
|
+
<p>The database contents, which can fluctuate within the bounds of the DB schema. Data can reference to other data, ideally via foreign keys.</p>
|
74
|
+
</li><li>
|
75
|
+
<p>A mix of the two, where code needs to be specifically tailored for some kind of data. A prominent example of such a mix would for instance be user roles: roles must be hardcoded in the code because security logic is tied to them. However, as users are assigned to roles in the database, roles also need to be persisted in the database. This is where Anchormodel comes into play.</p>
|
76
|
+
</li></ul>
|
70
77
|
|
71
|
-
<
|
72
|
-
<li>The code, which we can consider static within a given version. Code can
|
73
|
-
reference to other code, e.g. <code>node.parent = other_node</code>.</li>
|
74
|
-
<li>The database contents, which can fluctuate within the bounds of the DB schema.
|
75
|
-
Data can reference to other data, ideally via foreign keys.</li>
|
76
|
-
<li>A mix of the two, where code needs to be specifically tailored for some kind
|
77
|
-
of data. A prominent example of such a mix would for instance be user roles:
|
78
|
-
roles must be hardcoded in the code because security logic is tied to them.
|
79
|
-
However, as users are assigned to roles in the database, roles also need to be
|
80
|
-
persisted in the database. This is where Anchormodel comes into play.</li>
|
81
|
-
</ul>
|
78
|
+
<h2 id="label-Alternatives+coviering+the+same+use+case">Alternatives coviering the same use case</h2>
|
82
79
|
|
83
|
-
<
|
80
|
+
<h3 id="label-Enum">Enum</h3>
|
84
81
|
|
85
|
-
<
|
82
|
+
<p>In Rails and other frameworks, the third point in the listing above is typically achieved via Enums. Enums map either Integers or Strings to constants and therefore provide a link between the DB and the application code.</p>
|
86
83
|
|
87
|
-
<p>
|
88
|
-
achieved via Enums. Enums map either Integers or Strings to constants and
|
89
|
-
therefore provide a link between the DB and the application code.</p>
|
84
|
+
<p>However, at least in Rails, Enums provide very limited customization options. They are basic values that can be used in if-statements. Anchormodels however are regular classes and can easily be extended.</p>
|
90
85
|
|
91
|
-
<
|
92
|
-
They are basic values that can be used in if-statements. Anchormodels however
|
93
|
-
are regular classes and can easily be extended.</p>
|
86
|
+
<h3 id="label-ActiveEnum">ActiveEnum</h3>
|
94
87
|
|
95
|
-
<
|
88
|
+
<p>The gem (<a href="https://github.com/adzap/active_enum">ActiveEnum)</a> allows to create Enum-like classes that can be extended. However it only supports Integer keys. I find this unsatisfactory, as debugging with tools like <code>psql</code> or <code>mysql</code> is made unnecessarily hard when you only see numbers. Keys for enums should be meaningful, making you immediately understand what they stand for.</p>
|
96
89
|
|
97
|
-
<p>
|
98
|
-
Enum-like classes that can be extended. However it only supports Integer keys. I
|
99
|
-
find this unsatisfactory, as debugging with tools like <code>psql</code> or <code>mysql</code> is made
|
100
|
-
unnecessarily hard when you only see numbers. Keys for enums should be
|
101
|
-
meaningful, making you immediately understand what they stand for.</p>
|
90
|
+
<p>This is why Anchormodel is strictly relying on String keys corresponding to the entries of an Anchormodel.</p>
|
102
91
|
|
103
|
-
<
|
104
|
-
|
92
|
+
<h1 id="label-Installation">Installation</h1>
|
93
|
+
<ol><li>
|
94
|
+
<p>Add gem to Gemfile: <code>gem 'anchormodel'</code></p>
|
95
|
+
</li><li>
|
96
|
+
<p>In <code>application_record.rb</code>, add in the class body: <code>include Anchormodel::ModelMixin</code></p>
|
97
|
+
</li></ol>
|
105
98
|
|
106
|
-
<h1 id="example">
|
99
|
+
<h1 id="label-Basic+example">Basic example</h1>
|
107
100
|
|
108
101
|
<p><code>app/anchormodels/role.rb</code>:</p>
|
109
102
|
|
110
|
-
<pre class="code ruby"><code class="ruby"><span class='kw'>class</span> <span class='const'>
|
103
|
+
<pre class="code ruby"><code class="ruby"><span class='kw'>class</span> <span class='const'>Role</span> <span class='op'><</span> <span class='const'><span class='object_link'><a href="Anchormodel.html" title="Anchormodel (class)">Anchormodel</a></span></span>
|
104
|
+
<span class='comment'># Make <, > etc. based on <=> operator whic hwe will define below
|
105
|
+
</span> <span class='id identifier rubyid_include'>include</span> <span class='const'>Comparable</span>
|
106
|
+
|
111
107
|
<span class='comment'># Expose the attribute privilege_level
|
112
108
|
</span> <span class='id identifier rubyid_attr_reader'>attr_reader</span> <span class='symbol'>:privilege_level</span>
|
113
109
|
|
114
|
-
<span class='comment'>#
|
110
|
+
<span class='comment'># Define <=> to make user roles comparable based on the privilege level
|
115
111
|
</span> <span class='kw'>def</span> <span class='op'><=></span><span class='lparen'>(</span><span class='id identifier rubyid_other'>other</span><span class='rparen'>)</span>
|
116
|
-
<span class='
|
112
|
+
<span class='ivar'>@privilege_level</span> <span class='op'><=></span> <span class='id identifier rubyid_other'>other</span><span class='period'>.</span><span class='id identifier rubyid_privilege_level'>privilege_level</span>
|
117
113
|
<span class='kw'>end</span>
|
118
114
|
|
119
115
|
<span class='comment'># Declare all available roles
|
@@ -127,17 +123,21 @@ entries of an Anchormodel.</p>
|
|
127
123
|
|
128
124
|
<pre class="code ruby"><code class="ruby"><span class='comment'># The DB table `users` must have a String column `users.role`
|
129
125
|
</span><span class='kw'>class</span> <span class='const'>User</span> <span class='op'><</span> <span class='const'>ApplicationRecord</span>
|
130
|
-
<span class='
|
126
|
+
<span class='comment'># If `users.role` has an `NOT NULL` constraint, use:
|
127
|
+
</span> <span class='id identifier rubyid_belongs_to_anchormodel'>belongs_to_anchormodel</span> <span class='symbol'>:role</span>
|
128
|
+
|
129
|
+
<span class='comment'># If `users.role` can be `NULL`, use the following instead:
|
130
|
+
</span> <span class='id identifier rubyid_belongs_to_anchormodel'>belongs_to_anchormodel</span> <span class='symbol'>:role</span><span class='comma'>,</span> <span class='label'>optional:</span> <span class='kw'>true</span>
|
131
131
|
<span class='kw'>end</span>
|
132
132
|
</code></pre>
|
133
133
|
|
134
134
|
<p>You may now use the following methods:</p>
|
135
135
|
|
136
136
|
<pre class="code ruby"><code class="ruby"><span class='comment'># Retrieve all user roles:
|
137
|
-
</span><span class='const'>
|
137
|
+
</span><span class='const'>Role</span><span class='period'>.</span><span class='id identifier rubyid_all'>all</span>
|
138
138
|
|
139
139
|
<span class='comment'># Retrieve a specific role from the String and find its privilege level
|
140
|
-
</span><span class='const'>
|
140
|
+
</span><span class='const'>Role</span><span class='period'>.</span><span class='id identifier rubyid_find'>find</span><span class='lparen'>(</span><span class='symbol'>:guest</span><span class='rparen'>)</span><span class='period'>.</span><span class='id identifier rubyid_privilege_level'>privilege_level</span>
|
141
141
|
|
142
142
|
<span class='comment'># Implement a Rails helper that makes sure users can only edit other users that have a lower privilege level than themselves
|
143
143
|
</span><span class='kw'>def</span> <span class='id identifier rubyid_user_can_edit?'>user_can_edit?</span><span class='lparen'>(</span><span class='id identifier rubyid_this_user'>this_user</span><span class='comma'>,</span> <span class='id identifier rubyid_other_user'>other_user</span><span class='rparen'>)</span>
|
@@ -146,20 +146,91 @@ entries of an Anchormodel.</p>
|
|
146
146
|
|
147
147
|
<span class='comment'># Pretty print a user's role, e.g. using the Rails FastGettext gem:
|
148
148
|
</span><span class='id identifier rubyid_puts'>puts</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>"</span><span class='tstring_content'>User </span><span class='embexpr_beg'>#{</span><span class='ivar'>@user</span><span class='period'>.</span><span class='id identifier rubyid_name'>name</span><span class='embexpr_end'>}</span><span class='tstring_content'> has role </span><span class='embexpr_beg'>#{</span><span class='ivar'>@user</span><span class='period'>.</span><span class='id identifier rubyid_role'>role</span><span class='period'>.</span><span class='id identifier rubyid_label'>label</span><span class='embexpr_end'>}</span><span class='tstring_end'>"</span></span><span class='rparen'>)</span>
|
149
|
+
|
150
|
+
<span class='comment'># Check whether @user has role admin
|
151
|
+
</span><span class='ivar'>@user</span><span class='period'>.</span><span class='id identifier rubyid_role'>role</span><span class='period'>.</span><span class='id identifier rubyid_admin?'>admin?</span> <span class='comment'># true if and only if the role is admin (false otherwise)
|
152
|
+
</span></code></pre>
|
153
|
+
|
154
|
+
<h1 id="label-Rails+Enum+style+model+methods">Rails Enum style model methods</h1>
|
155
|
+
|
156
|
+
<p>By default, Anchormodel adds three kinds of methods for each key to the model:</p>
|
157
|
+
<ul><li>
|
158
|
+
<p>a reader (getter)</p>
|
159
|
+
</li><li>
|
160
|
+
<p>a writer (setter)</p>
|
161
|
+
</li><li>
|
162
|
+
<p>a Rails scope</p>
|
163
|
+
</li></ul>
|
164
|
+
|
165
|
+
<p>For instance:</p>
|
166
|
+
|
167
|
+
<pre class="code ruby"><code class="ruby"><span class='kw'>class</span> <span class='const'>User</span> <span class='op'><</span> <span class='const'>ApplicationRecord</span>
|
168
|
+
<span class='id identifier rubyid_belongs_to_anchormodel'>belongs_to_anchormodel</span> <span class='symbol'>:role</span> <span class='comment'># where Role has keys :guest, :manager and :admin
|
169
|
+
</span> <span class='id identifier rubyid_belongs_to_anchormodel'>belongs_to_anchormodel</span> <span class='symbol'>:shape</span> <span class='comment'># where Shape has keys :circle and :rectangle
|
170
|
+
</span><span class='kw'>end</span>
|
171
|
+
|
172
|
+
<span class='comment'># User now implements the following methods, given that @user is retrieved as follows:
|
173
|
+
</span><span class='ivar'>@user</span> <span class='op'>=</span> <span class='const'>User</span><span class='period'>.</span><span class='id identifier rubyid_first'>first</span> <span class='comment'># for example
|
174
|
+
</span>
|
175
|
+
<span class='comment'># Readers
|
176
|
+
</span><span class='ivar'>@user</span><span class='period'>.</span><span class='id identifier rubyid_guest?'>guest?</span> <span class='comment'># same as @user.role.guest?
|
177
|
+
</span><span class='ivar'>@user</span><span class='period'>.</span><span class='id identifier rubyid_manager?'>manager?</span>
|
178
|
+
<span class='ivar'>@user</span><span class='period'>.</span><span class='id identifier rubyid_admin?'>admin?</span>
|
179
|
+
<span class='ivar'>@user</span><span class='period'>.</span><span class='id identifier rubyid_rectangle?'>rectangle?</span> <span class='comment'># same as @user.shape.rectangle?
|
180
|
+
</span><span class='ivar'>@user</span><span class='period'>.</span><span class='id identifier rubyid_circle?'>circle?</span>
|
181
|
+
<span class='comment'># Writers
|
182
|
+
</span><span class='ivar'>@user</span><span class='period'>.</span><span class='id identifier rubyid_guest!'>guest!</span> <span class='comment'># same as @user.role = Role.find(:guest)
|
183
|
+
</span><span class='ivar'>@user</span><span class='period'>.</span><span class='id identifier rubyid_manager!'>manager!</span>
|
184
|
+
<span class='ivar'>@user</span><span class='period'>.</span><span class='id identifier rubyid_admin!'>admin!</span>
|
185
|
+
<span class='ivar'>@user</span><span class='period'>.</span><span class='id identifier rubyid_rectangle!'>rectangle!</span> <span class='comment'># same as @user.shape = Shape.find(:rectangle)
|
186
|
+
</span><span class='ivar'>@user</span><span class='period'>.</span><span class='id identifier rubyid_circle!'>circle!</span>
|
187
|
+
<span class='comment'># Scopes
|
188
|
+
</span><span class='const'>User</span><span class='period'>.</span><span class='id identifier rubyid_guest'>guest</span> <span class='comment'># same as User.where(role: 'guest')
|
189
|
+
</span><span class='const'>User</span><span class='period'>.</span><span class='id identifier rubyid_manager'>manager</span>
|
190
|
+
<span class='const'>User</span><span class='period'>.</span><span class='id identifier rubyid_admin'>admin</span>
|
191
|
+
<span class='const'>User</span><span class='period'>.</span><span class='id identifier rubyid_rectangle'>rectangle</span> <span class='comment'># same as User.where(shape: 'rectangle')
|
192
|
+
</span><span class='const'>User</span><span class='period'>.</span><span class='id identifier rubyid_circle'>circle</span>
|
193
|
+
</code></pre>
|
194
|
+
|
195
|
+
<p>This behavior is similar as the one from Rails Enums. If you want to disable it, use:</p>
|
196
|
+
|
197
|
+
<pre class="code ruby"><code class="ruby"><span class='kw'>class</span> <span class='const'>User</span> <span class='op'><</span> <span class='const'>ApplicationRecord</span>
|
198
|
+
<span class='id identifier rubyid_belongs_to_anchormodel'>belongs_to_anchormodel</span> <span class='symbol'>:role</span><span class='comma'>,</span> <span class='label'>model_readers:</span> <span class='kw'>false</span><span class='comma'>,</span> <span class='label'>model_writers:</span> <span class='kw'>false</span><span class='comma'>,</span> <span class='label'>model_scopes:</span> <span class='kw'>false</span>
|
199
|
+
<span class='comment'># or, equivalent, to disable all at once:
|
200
|
+
</span> <span class='id identifier rubyid_belongs_to_anchormodel'>belongs_to_anchormodel</span> <span class='symbol'>:role</span><span class='comma'>,</span> <span class='label'>model_methods:</span> <span class='kw'>false</span>
|
201
|
+
<span class='kw'>end</span>
|
202
|
+
</code></pre>
|
203
|
+
|
204
|
+
<h1 id="label-Calling+a+column+differently+than+the+Anchormodel">Calling a column differently than the Anchormodel</h1>
|
205
|
+
|
206
|
+
<p>If your column name (and the model’s attribute) is called differently than the Anchormodel, you may give the Anchormodel’s class as the second argument. For example:</p>
|
207
|
+
|
208
|
+
<pre class="code ruby"><code class="ruby"><span class='comment'># app/anchormodels/color.rb
|
209
|
+
</span><span class='kw'>class</span> <span class='const'>Color</span> <span class='op'><</span> <span class='const'><span class='object_link'><a href="Anchormodel.html" title="Anchormodel (class)">Anchormodel</a></span></span>
|
210
|
+
<span class='id identifier rubyid_new'>new</span> <span class='symbol'>:green</span>
|
211
|
+
<span class='id identifier rubyid_new'>new</span> <span class='symbol'>:red</span>
|
212
|
+
<span class='kw'>end</span>
|
213
|
+
|
214
|
+
<span class='comment'># app/models/user.rb
|
215
|
+
</span><span class='kw'>class</span> <span class='const'>User</span> <span class='op'><</span> <span class='const'>ApplicationRecord</span>
|
216
|
+
<span class='id identifier rubyid_belongs_to_anchormodel'>belongs_to_anchormodel</span> <span class='symbol'>:favorite_color</span><span class='comma'>,</span> <span class='const'>Color</span>
|
217
|
+
<span class='kw'>end</span>
|
149
218
|
</code></pre>
|
150
219
|
|
151
|
-
<
|
220
|
+
<h2 id="label-Having+multiple+attributes+to+the+same+Anchormodel">Having multiple attributes to the same Anchormodel</h2>
|
152
221
|
|
153
|
-
<
|
154
|
-
|
155
|
-
<
|
156
|
-
</
|
222
|
+
<p>If you want to have multiple attributes in the same model pointing to the same Anchormodel, you need to disable <code>model_methods</code> for at least one of them (otherwise the model methods will clash in your model class):</p>
|
223
|
+
|
224
|
+
<pre class="code ruby"><code class="ruby"><span class='comment'># app/models/user.rb
|
225
|
+
</span> <span class='id identifier rubyid_belongs_to_anchormodel'>belongs_to_anchormodel</span> <span class='symbol'>:role</span>
|
226
|
+
<span class='id identifier rubyid_belongs_to_anchormodel'>belongs_to_anchormodel</span> <span class='symbol'>:secondary_role</span><span class='comma'>,</span> <span class='const'>Role</span><span class='comma'>,</span> <span class='label'>model_methods:</span> <span class='kw'>false</span>
|
227
|
+
</code></pre>
|
157
228
|
</div></div>
|
158
229
|
|
159
230
|
<div id="footer">
|
160
|
-
Generated on
|
231
|
+
Generated on Tue Jan 24 20:27:59 2023 by
|
161
232
|
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
162
|
-
0.9.28 (ruby-3.
|
233
|
+
0.9.28 (ruby-3.1.3).
|
163
234
|
</div>
|
164
235
|
|
165
236
|
</div>
|