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.
- checksums.yaml +4 -4
- data/.ruby-version +1 -1
- data/CHANGELOG.md +14 -0
- data/EXAMPLES.md +408 -0
- data/Gemfile.lock +1 -1
- data/README.md +43 -1
- data/VERSION +1 -1
- data/anchormodel.gemspec +3 -3
- data/bin/test +9 -0
- data/doc/Anchormodel/ActiveModelTypeValueMulti.html +204 -42
- data/doc/Anchormodel/ActiveModelTypeValueSingle.html +243 -54
- data/doc/Anchormodel/Attribute.html +60 -37
- data/doc/Anchormodel/ModelMixin.html +166 -16
- data/doc/Anchormodel/SimpleFormInputs/Helpers/AnchormodelInputsCommon.html +82 -21
- data/doc/Anchormodel/SimpleFormInputs/Helpers.html +2 -11
- data/doc/Anchormodel/SimpleFormInputs.html +2 -11
- data/doc/Anchormodel/Util.html +497 -38
- data/doc/Anchormodel/Version.html +2 -20
- data/doc/Anchormodel.html +536 -129
- data/doc/AnchormodelCheckBoxesInput.html +22 -1
- data/doc/AnchormodelGenerator.html +64 -13
- data/doc/AnchormodelInput.html +24 -1
- data/doc/AnchormodelRadioButtonsInput.html +22 -1
- data/doc/_index.html +16 -1
- data/doc/class_list.html +1 -1
- data/doc/file.README.html +40 -2
- data/doc/index.html +40 -2
- data/doc/method_list.html +57 -17
- data/doc/top-level-namespace.html +1 -1
- data/lib/anchormodel/active_model_type_value_multi.rb +31 -5
- data/lib/anchormodel/active_model_type_value_single.rb +34 -6
- data/lib/anchormodel/attribute.rb +20 -8
- data/lib/anchormodel/model_mixin.rb +43 -8
- data/lib/anchormodel/simple_form_inputs/anchormodel_check_boxes_input.rb +7 -0
- data/lib/anchormodel/simple_form_inputs/anchormodel_input.rb +9 -0
- data/lib/anchormodel/simple_form_inputs/anchormodel_radio_buttons_input.rb +7 -0
- data/lib/anchormodel/simple_form_inputs/helpers/anchormodel_inputs_common.rb +14 -0
- data/lib/anchormodel/util.rb +102 -17
- data/lib/anchormodel.rb +109 -15
- data/lib/generators/anchormodel/anchormodel_generator.rb +8 -0
- data/test/active_record_model/user_test.rb +221 -10
- data/test/dummy/app/anchormodels/animal.rb +1 -0
- metadata +3 -1
|
@@ -106,8 +106,29 @@
|
|
|
106
106
|
|
|
107
107
|
</div>
|
|
108
108
|
|
|
109
|
+
<h2>Overview</h2><div class="docstring">
|
|
110
|
+
<div class="discussion">
|
|
111
|
+
|
|
112
|
+
<p>SimpleForm input for a collection-valued anchormodel attribute (<code>belongs_to_anchormodels</code>), rendered as check boxes (one per anchormodel key).</p>
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
</div>
|
|
116
|
+
</div>
|
|
117
|
+
<div class="tags">
|
|
118
|
+
|
|
119
|
+
<div class="examples">
|
|
120
|
+
<p class="tag_title">Examples:</p>
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
<pre class="example code"><code><%= simple_form_for user do |f| %>
|
|
124
|
+
<%= f.input :animals, as: :anchormodel_check_boxes %>
|
|
125
|
+
<% end %></code></pre>
|
|
126
|
+
|
|
127
|
+
</div>
|
|
109
128
|
|
|
110
129
|
|
|
130
|
+
</div>
|
|
131
|
+
|
|
111
132
|
|
|
112
133
|
|
|
113
134
|
|
|
@@ -130,7 +151,7 @@
|
|
|
130
151
|
</div>
|
|
131
152
|
|
|
132
153
|
<div id="footer">
|
|
133
|
-
Generated on Wed May 13
|
|
154
|
+
Generated on Wed May 13 15:48:25 2026 by
|
|
134
155
|
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
|
135
156
|
0.9.28 (ruby-3.3.5).
|
|
136
157
|
</div>
|
|
@@ -101,8 +101,28 @@
|
|
|
101
101
|
|
|
102
102
|
</div>
|
|
103
103
|
|
|
104
|
+
<h2>Overview</h2><div class="docstring">
|
|
105
|
+
<div class="discussion">
|
|
106
|
+
|
|
107
|
+
<p>Rails generator for scaffolding a new anchormodel.</p>
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
</div>
|
|
111
|
+
</div>
|
|
112
|
+
<div class="tags">
|
|
113
|
+
|
|
114
|
+
<div class="examples">
|
|
115
|
+
<p class="tag_title">Examples:</p>
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
<pre class="example code"><code><span class='id identifier rubyid_rails'>rails</span> <span class='id identifier rubyid_generate'>generate</span> <span class='id identifier rubyid_anchormodel'>anchormodel</span> <span class='const'>Role</span>
|
|
119
|
+
<span class='comment'># → creates app/anchormodels/role.rb</span></code></pre>
|
|
120
|
+
|
|
121
|
+
</div>
|
|
104
122
|
|
|
105
123
|
|
|
124
|
+
</div>
|
|
125
|
+
|
|
106
126
|
|
|
107
127
|
|
|
108
128
|
|
|
@@ -119,7 +139,7 @@
|
|
|
119
139
|
<li class="public ">
|
|
120
140
|
<span class="summary_signature">
|
|
121
141
|
|
|
122
|
-
<a href="#add_anchormodel-instance_method" title="#add_anchormodel (instance method)">#<strong>add_anchormodel</strong> ⇒
|
|
142
|
+
<a href="#add_anchormodel-instance_method" title="#add_anchormodel (instance method)">#<strong>add_anchormodel</strong> ⇒ void </a>
|
|
123
143
|
|
|
124
144
|
|
|
125
145
|
|
|
@@ -133,7 +153,9 @@
|
|
|
133
153
|
|
|
134
154
|
|
|
135
155
|
|
|
136
|
-
<span class="summary_desc"><div class='inline'
|
|
156
|
+
<span class="summary_desc"><div class='inline'>
|
|
157
|
+
<p>Writes the new anchormodel file from the ERB template.</p>
|
|
158
|
+
</div></span>
|
|
137
159
|
|
|
138
160
|
</li>
|
|
139
161
|
|
|
@@ -151,28 +173,57 @@
|
|
|
151
173
|
<div class="method_details first">
|
|
152
174
|
<h3 class="signature first" id="add_anchormodel-instance_method">
|
|
153
175
|
|
|
154
|
-
#<strong>add_anchormodel</strong> ⇒ <tt>
|
|
176
|
+
#<strong>add_anchormodel</strong> ⇒ <tt>void</tt>
|
|
155
177
|
|
|
156
178
|
|
|
157
179
|
|
|
158
180
|
|
|
159
181
|
|
|
160
|
-
</h3><
|
|
182
|
+
</h3><div class="docstring">
|
|
183
|
+
<div class="discussion">
|
|
184
|
+
<p class="note returns_void">This method returns an undefined value.</p>
|
|
185
|
+
<p>Writes the new anchormodel file from the ERB template.</p>
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
</div>
|
|
189
|
+
</div>
|
|
190
|
+
<div class="tags">
|
|
191
|
+
|
|
192
|
+
<p class="tag_title">Raises:</p>
|
|
193
|
+
<ul class="raise">
|
|
194
|
+
|
|
195
|
+
<li>
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
<span class='type'>(<tt>RuntimeError</tt>)</span>
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
—
|
|
203
|
+
<div class='inline'>
|
|
204
|
+
<p>if NAME is blank.</p>
|
|
205
|
+
</div>
|
|
206
|
+
|
|
207
|
+
</li>
|
|
208
|
+
|
|
209
|
+
</ul>
|
|
210
|
+
|
|
211
|
+
</div><table class="source_code">
|
|
161
212
|
<tr>
|
|
162
213
|
<td>
|
|
163
214
|
<pre class="lines">
|
|
164
215
|
|
|
165
216
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
217
|
+
12
|
|
218
|
+
13
|
|
219
|
+
14
|
|
220
|
+
15
|
|
221
|
+
16
|
|
222
|
+
17
|
|
223
|
+
18</pre>
|
|
173
224
|
</td>
|
|
174
225
|
<td>
|
|
175
|
-
<pre class="code"><span class="info file"># File 'lib/generators/anchormodel/anchormodel_generator.rb', line
|
|
226
|
+
<pre class="code"><span class="info file"># File 'lib/generators/anchormodel/anchormodel_generator.rb', line 12</span>
|
|
176
227
|
|
|
177
228
|
<span class='kw'>def</span> <span class='id identifier rubyid_add_anchormodel'>add_anchormodel</span>
|
|
178
229
|
<span class='id identifier rubyid_fail'>fail</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>NAME must be present.</span><span class='tstring_end'>'</span></span><span class='rparen'>)</span> <span class='kw'>if</span> <span class='id identifier rubyid_name'>name</span><span class='period'>.</span><span class='id identifier rubyid_blank?'>blank?</span>
|
|
@@ -191,7 +242,7 @@
|
|
|
191
242
|
</div>
|
|
192
243
|
|
|
193
244
|
<div id="footer">
|
|
194
|
-
Generated on Wed May 13
|
|
245
|
+
Generated on Wed May 13 15:48:25 2026 by
|
|
195
246
|
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
|
196
247
|
0.9.28 (ruby-3.3.5).
|
|
197
248
|
</div>
|
data/doc/AnchormodelInput.html
CHANGED
|
@@ -106,7 +106,30 @@
|
|
|
106
106
|
|
|
107
107
|
</div>
|
|
108
108
|
|
|
109
|
+
<h2>Overview</h2><div class="docstring">
|
|
110
|
+
<div class="discussion">
|
|
111
|
+
|
|
112
|
+
<p>SimpleForm input for an anchormodel attribute. Renders a <code><select></code> collection whose options are the entries of the bound anchormodel.</p>
|
|
113
|
+
|
|
114
|
+
<p>Auto-detected by SimpleForm because the attribute’s AR type is <code>:anchormodel</code>.</p>
|
|
115
|
+
|
|
109
116
|
|
|
117
|
+
</div>
|
|
118
|
+
</div>
|
|
119
|
+
<div class="tags">
|
|
120
|
+
|
|
121
|
+
<div class="examples">
|
|
122
|
+
<p class="tag_title">Examples:</p>
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
<pre class="example code"><code><%= simple_form_for user do |f| %>
|
|
126
|
+
<%= f.input :role %>
|
|
127
|
+
<% end %></code></pre>
|
|
128
|
+
|
|
129
|
+
</div>
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
</div>
|
|
110
133
|
|
|
111
134
|
|
|
112
135
|
|
|
@@ -130,7 +153,7 @@
|
|
|
130
153
|
</div>
|
|
131
154
|
|
|
132
155
|
<div id="footer">
|
|
133
|
-
Generated on Wed May 13
|
|
156
|
+
Generated on Wed May 13 15:48:25 2026 by
|
|
134
157
|
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
|
135
158
|
0.9.28 (ruby-3.3.5).
|
|
136
159
|
</div>
|
|
@@ -106,8 +106,29 @@
|
|
|
106
106
|
|
|
107
107
|
</div>
|
|
108
108
|
|
|
109
|
+
<h2>Overview</h2><div class="docstring">
|
|
110
|
+
<div class="discussion">
|
|
111
|
+
|
|
112
|
+
<p>SimpleForm input for a single-value anchormodel attribute, rendered as radio buttons. Unsuitable for collection attributes — use <span class='object_link'><a href="AnchormodelCheckBoxesInput.html" title="AnchormodelCheckBoxesInput (class)">AnchormodelCheckBoxesInput</a></span> for those.</p>
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
</div>
|
|
116
|
+
</div>
|
|
117
|
+
<div class="tags">
|
|
118
|
+
|
|
119
|
+
<div class="examples">
|
|
120
|
+
<p class="tag_title">Examples:</p>
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
<pre class="example code"><code><%= simple_form_for user do |f| %>
|
|
124
|
+
<%= f.input :role, as: :anchormodel_radio_buttons %>
|
|
125
|
+
<% end %></code></pre>
|
|
126
|
+
|
|
127
|
+
</div>
|
|
109
128
|
|
|
110
129
|
|
|
130
|
+
</div>
|
|
131
|
+
|
|
111
132
|
|
|
112
133
|
|
|
113
134
|
|
|
@@ -130,7 +151,7 @@
|
|
|
130
151
|
</div>
|
|
131
152
|
|
|
132
153
|
<div id="footer">
|
|
133
|
-
Generated on Wed May 13
|
|
154
|
+
Generated on Wed May 13 15:48:25 2026 by
|
|
134
155
|
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
|
135
156
|
0.9.28 (ruby-3.3.5).
|
|
136
157
|
</div>
|
data/doc/_index.html
CHANGED
|
@@ -152,6 +152,21 @@
|
|
|
152
152
|
</ul>
|
|
153
153
|
|
|
154
154
|
|
|
155
|
+
<ul id="alpha_I" class="alpha">
|
|
156
|
+
<li class="letter">I</li>
|
|
157
|
+
<ul>
|
|
158
|
+
|
|
159
|
+
<li>
|
|
160
|
+
<span class='object_link'><a href="Anchormodel/InvalidKey.html" title="Anchormodel::InvalidKey (class)">InvalidKey</a></span>
|
|
161
|
+
|
|
162
|
+
<small>(Anchormodel)</small>
|
|
163
|
+
|
|
164
|
+
</li>
|
|
165
|
+
|
|
166
|
+
</ul>
|
|
167
|
+
</ul>
|
|
168
|
+
|
|
169
|
+
|
|
155
170
|
<ul id="alpha_M" class="alpha">
|
|
156
171
|
<li class="letter">M</li>
|
|
157
172
|
<ul>
|
|
@@ -220,7 +235,7 @@
|
|
|
220
235
|
</div>
|
|
221
236
|
|
|
222
237
|
<div id="footer">
|
|
223
|
-
Generated on Wed May 13
|
|
238
|
+
Generated on Wed May 13 15:48:24 2026 by
|
|
224
239
|
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
|
225
240
|
0.9.28 (ruby-3.3.5).
|
|
226
241
|
</div>
|
data/doc/class_list.html
CHANGED
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
|
|
44
44
|
<ul id="full_list" class="class">
|
|
45
45
|
<li id="object_" class="odd"><div class="item" style="padding-left:30px"><span class='object_link'><a href="top-level-namespace.html" title="Top Level Namespace (root)">Top Level Namespace</a></span></div></li>
|
|
46
|
-
<li id='object_Anchormodel' class='even'><div class='item' style='padding-left:30px'><a class='toggle'></a> <span class='object_link'><a href="Anchormodel.html" title="Anchormodel (class)">Anchormodel</a></span> < Object<small class='search_info'>Top Level Namespace</small></div><ul><li id='object_Anchormodel::ActiveModelTypeValueMulti' class='collapsed odd'><div class='item' style='padding-left:45px'><span class='object_link'><a href="Anchormodel/ActiveModelTypeValueMulti.html" title="Anchormodel::ActiveModelTypeValueMulti (class)">ActiveModelTypeValueMulti</a></span> < ActiveModelTypeValueSingle<small class='search_info'>Anchormodel</small></div></li><li id='object_Anchormodel::ActiveModelTypeValueSingle' class='collapsed even'><div class='item' style='padding-left:45px'><span class='object_link'><a href="Anchormodel/ActiveModelTypeValueSingle.html" title="Anchormodel::ActiveModelTypeValueSingle (class)">ActiveModelTypeValueSingle</a></span> < Value<small class='search_info'>Anchormodel</small></div></li><li id='object_Anchormodel::Attribute' class='collapsed odd'><div class='item' style='padding-left:45px'><span class='object_link'><a href="Anchormodel/Attribute.html" title="Anchormodel::Attribute (class)">Attribute</a></span> < Object<small class='search_info'>Anchormodel</small></div></li><li id='object_Anchormodel::
|
|
46
|
+
<li id='object_Anchormodel' class='even'><div class='item' style='padding-left:30px'><a class='toggle'></a> <span class='object_link'><a href="Anchormodel.html" title="Anchormodel (class)">Anchormodel</a></span> < Object<small class='search_info'>Top Level Namespace</small></div><ul><li id='object_Anchormodel::ActiveModelTypeValueMulti' class='collapsed odd'><div class='item' style='padding-left:45px'><span class='object_link'><a href="Anchormodel/ActiveModelTypeValueMulti.html" title="Anchormodel::ActiveModelTypeValueMulti (class)">ActiveModelTypeValueMulti</a></span> < ActiveModelTypeValueSingle<small class='search_info'>Anchormodel</small></div></li><li id='object_Anchormodel::ActiveModelTypeValueSingle' class='collapsed even'><div class='item' style='padding-left:45px'><span class='object_link'><a href="Anchormodel/ActiveModelTypeValueSingle.html" title="Anchormodel::ActiveModelTypeValueSingle (class)">ActiveModelTypeValueSingle</a></span> < Value<small class='search_info'>Anchormodel</small></div></li><li id='object_Anchormodel::Attribute' class='collapsed odd'><div class='item' style='padding-left:45px'><span class='object_link'><a href="Anchormodel/Attribute.html" title="Anchormodel::Attribute (class)">Attribute</a></span> < Object<small class='search_info'>Anchormodel</small></div></li><li id='object_Anchormodel::InvalidKey' class='collapsed even'><div class='item' style='padding-left:45px'><span class='object_link'><a href="Anchormodel/InvalidKey.html" title="Anchormodel::InvalidKey (class)">InvalidKey</a></span> < RuntimeError<small class='search_info'>Anchormodel</small></div></li><li id='object_Anchormodel::ModelMixin' class='collapsed odd'><div class='item' style='padding-left:45px'><span class='object_link'><a href="Anchormodel/ModelMixin.html" title="Anchormodel::ModelMixin (module)">ModelMixin</a></span><small class='search_info'>Anchormodel</small></div></li><li id='object_Anchormodel::SimpleFormInputs' class='collapsed even'><div class='item' style='padding-left:45px'><a class='toggle'></a> <span class='object_link'><a href="Anchormodel/SimpleFormInputs.html" title="Anchormodel::SimpleFormInputs (module)">SimpleFormInputs</a></span><small class='search_info'>Anchormodel</small></div><ul><li id='object_Anchormodel::SimpleFormInputs::Helpers' class='collapsed'><div class='item' style='padding-left:60px'><a class='toggle'></a> <span class='object_link'><a href="Anchormodel/SimpleFormInputs/Helpers.html" title="Anchormodel::SimpleFormInputs::Helpers (module)">Helpers</a></span><small class='search_info'>Anchormodel::SimpleFormInputs</small></div><ul><li id='object_Anchormodel::SimpleFormInputs::Helpers::AnchormodelInputsCommon' class='collapsed'><div class='item' style='padding-left:75px'><span class='object_link'><a href="Anchormodel/SimpleFormInputs/Helpers/AnchormodelInputsCommon.html" title="Anchormodel::SimpleFormInputs::Helpers::AnchormodelInputsCommon (module)">AnchormodelInputsCommon</a></span><small class='search_info'>Anchormodel::SimpleFormInputs::Helpers</small></div></li></ul></li></ul></li><li id='object_Anchormodel::Util' class='collapsed odd'><div class='item' style='padding-left:45px'><span class='object_link'><a href="Anchormodel/Util.html" title="Anchormodel::Util (module)">Util</a></span><small class='search_info'>Anchormodel</small></div></li><li id='object_Anchormodel::Version' class='collapsed even'><div class='item' style='padding-left:45px'><span class='object_link'><a href="Anchormodel/Version.html" title="Anchormodel::Version (module)">Version</a></span><small class='search_info'>Anchormodel</small></div></li></ul></li><li id='object_AnchormodelCheckBoxesInput' class='odd'><div class='item' style='padding-left:30px'><span class='object_link'><a href="AnchormodelCheckBoxesInput.html" title="AnchormodelCheckBoxesInput (class)">AnchormodelCheckBoxesInput</a></span> < CollectionCheckBoxesInput<small class='search_info'>Top Level Namespace</small></div></li><li id='object_AnchormodelGenerator' class='even'><div class='item' style='padding-left:30px'><span class='object_link'><a href="AnchormodelGenerator.html" title="AnchormodelGenerator (class)">AnchormodelGenerator</a></span> < NamedBase<small class='search_info'>Top Level Namespace</small></div></li><li id='object_AnchormodelInput' class='odd'><div class='item' style='padding-left:30px'><span class='object_link'><a href="AnchormodelInput.html" title="AnchormodelInput (class)">AnchormodelInput</a></span> < CollectionSelectInput<small class='search_info'>Top Level Namespace</small></div></li><li id='object_AnchormodelRadioButtonsInput' class='even'><div class='item' style='padding-left:30px'><span class='object_link'><a href="AnchormodelRadioButtonsInput.html" title="AnchormodelRadioButtonsInput (class)">AnchormodelRadioButtonsInput</a></span> < CollectionRadioButtonsInput<small class='search_info'>Top Level Namespace</small></div></li>
|
|
47
47
|
|
|
48
48
|
</ul>
|
|
49
49
|
</div>
|
data/doc/file.README.html
CHANGED
|
@@ -64,6 +64,8 @@
|
|
|
64
64
|
|
|
65
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
66
|
|
|
67
|
+
<p>For a tour of real-world usage patterns — ordered enums with <code>Comparable</code>, state machines, polymorphic class registries, multi-key collection attributes, cross-anchormodel references, and more — see <a href="EXAMPLES_md.html">EXAMPLES.md</a>.</p>
|
|
68
|
+
|
|
67
69
|
<h1 id="label-Use+case">Use case</h1>
|
|
68
70
|
|
|
69
71
|
<p>Typically, a Rails application consists of three kinds of state:</p>
|
|
@@ -144,8 +146,14 @@
|
|
|
144
146
|
<pre class="code ruby"><code class="ruby"><span class='comment'># Retrieve all user roles:
|
|
145
147
|
</span><span class='const'>Role</span><span class='period'>.</span><span class='id identifier rubyid_all'>all</span>
|
|
146
148
|
|
|
147
|
-
<span class='comment'># Retrieve a specific role
|
|
149
|
+
<span class='comment'># Retrieve a specific role. `find` accepts a String, a Symbol, or `nil` (returns nil).
|
|
148
150
|
</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>
|
|
151
|
+
<span class='const'>Role</span><span class='period'>.</span><span class='id identifier rubyid_find'>find</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>guest</span><span class='tstring_end'>'</span></span><span class='rparen'>)</span><span class='period'>.</span><span class='id identifier rubyid_privilege_level'>privilege_level</span> <span class='comment'># equivalent
|
|
152
|
+
</span>
|
|
153
|
+
<span class='comment'># Assignment accepts a String, Symbol, or Anchormodel instance:
|
|
154
|
+
</span><span class='ivar'>@user</span><span class='period'>.</span><span class='id identifier rubyid_role'>role</span> <span class='op'>=</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>admin</span><span class='tstring_end'>'</span></span>
|
|
155
|
+
<span class='ivar'>@user</span><span class='period'>.</span><span class='id identifier rubyid_role'>role</span> <span class='op'>=</span> <span class='symbol'>:admin</span>
|
|
156
|
+
<span class='ivar'>@user</span><span class='period'>.</span><span class='id identifier rubyid_role'>role</span> <span class='op'>=</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'>:admin</span><span class='rparen'>)</span>
|
|
149
157
|
|
|
150
158
|
<span class='comment'># Implement a Rails helper that makes sure users can only edit other users that have a lower privilege level than themselves
|
|
151
159
|
</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>
|
|
@@ -159,6 +167,19 @@
|
|
|
159
167
|
</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)
|
|
160
168
|
</span></code></pre>
|
|
161
169
|
|
|
170
|
+
<h2 id="label-Error+handling">Error handling</h2>
|
|
171
|
+
|
|
172
|
+
<p>Anchormodel raises <code>Anchormodel::InvalidKey</code> whenever an unknown key is supplied — from <code>find</code>, from attribute writers, and from the bulk-key scopes shown below:</p>
|
|
173
|
+
|
|
174
|
+
<pre class="code ruby"><code class="ruby"><span class='kw'>begin</span>
|
|
175
|
+
<span class='const'>Role</span><span class='period'>.</span><span class='id identifier rubyid_find'>find</span><span class='lparen'>(</span><span class='symbol'>:does_not_exist</span><span class='rparen'>)</span>
|
|
176
|
+
<span class='kw'>rescue</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="Anchormodel/InvalidKey.html" title="Anchormodel::InvalidKey (class)">InvalidKey</a></span></span> <span class='op'>=></span> <span class='id identifier rubyid_e'>e</span>
|
|
177
|
+
<span class='comment'># e.message: "Retrieved undefined anchor model key :does_not_exist for Role."
|
|
178
|
+
</span><span class='kw'>end</span>
|
|
179
|
+
</code></pre>
|
|
180
|
+
|
|
181
|
+
<p><code>Anchormodel::InvalidKey</code> inherits from <code>RuntimeError</code>, so existing <code>rescue RuntimeError</code> blocks remain compatible while allowing the narrower <code>rescue Anchormodel::InvalidKey</code>.</p>
|
|
182
|
+
|
|
162
183
|
<p>Your form could look something like this:</p>
|
|
163
184
|
|
|
164
185
|
<pre class="code ruby"><code class="ruby"><%= form_with(model: user) do |form| %>
|
|
@@ -302,6 +323,23 @@
|
|
|
302
323
|
|
|
303
324
|
<p>Note that no other methods of Set are overwritten at this point - if you use any other methods mutating the underlying Set, your changes will not be applied.</p>
|
|
304
325
|
|
|
326
|
+
<h2 id="label-Querying+a+collection+of+Anchormodels">Querying a collection of Anchormodels</h2>
|
|
327
|
+
|
|
328
|
+
<p>Because keys are stored as a CSV string in a single column, the standard Rails idiom <code>Model.where(col: array)</code> does <strong>not</strong> work for <code>belongs_to_anchormodels</code> attributes — it compiles to an <code>IN (...)</code> clause that compares against the full column value (e.g. <code>"cat,dog"</code>) rather than the individual entries.</p>
|
|
329
|
+
|
|
330
|
+
<p>Anchormodel provides two helper scopes for bulk-key queries:</p>
|
|
331
|
+
|
|
332
|
+
<pre class="code ruby"><code class="ruby"><span class='comment'># Users that hold at least one of the given keys
|
|
333
|
+
</span><span class='const'>User</span><span class='period'>.</span><span class='id identifier rubyid_with_any_animals'>with_any_animals</span><span class='lparen'>(</span><span class='symbol'>:cat</span><span class='comma'>,</span> <span class='symbol'>:dog</span><span class='rparen'>)</span>
|
|
334
|
+
|
|
335
|
+
<span class='comment'># Users that hold every given key
|
|
336
|
+
</span><span class='const'>User</span><span class='period'>.</span><span class='id identifier rubyid_with_all_animals'>with_all_animals</span><span class='lparen'>(</span><span class='symbol'>:cat</span><span class='comma'>,</span> <span class='symbol'>:dog</span><span class='rparen'>)</span>
|
|
337
|
+
</code></pre>
|
|
338
|
+
|
|
339
|
+
<p>Both scopes accept <code>String</code>, <code>Symbol</code>, or <code>Anchormodel</code> instances (and nested arrays), and raise <code>Anchormodel::InvalidKey</code> on invalid keys. They are always defined for every <code>belongs_to_anchormodels</code> attribute (independent of the <code>model_scopes</code> setting), named <code>with_any_<attribute_name></code> / <code>with_all_<attribute_name></code>.</p>
|
|
340
|
+
|
|
341
|
+
<p>For a single key, the per-key scope generated by <code>model_scopes</code> (e.g. <code>User.cat</code>) is the most concise option.</p>
|
|
342
|
+
|
|
305
343
|
<h2 id="label-Basic+rails+form+for+a+collection+of+Anchormodels">Basic rails form for a collection of Anchormodels</h2>
|
|
306
344
|
|
|
307
345
|
<pre class="code ruby"><code class="ruby"><%= form_with(model: user) do |form| %>
|
|
@@ -339,7 +377,7 @@
|
|
|
339
377
|
</div></div>
|
|
340
378
|
|
|
341
379
|
<div id="footer">
|
|
342
|
-
Generated on Wed May 13
|
|
380
|
+
Generated on Wed May 13 15:48:24 2026 by
|
|
343
381
|
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
|
344
382
|
0.9.28 (ruby-3.3.5).
|
|
345
383
|
</div>
|
data/doc/index.html
CHANGED
|
@@ -64,6 +64,8 @@
|
|
|
64
64
|
|
|
65
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
66
|
|
|
67
|
+
<p>For a tour of real-world usage patterns — ordered enums with <code>Comparable</code>, state machines, polymorphic class registries, multi-key collection attributes, cross-anchormodel references, and more — see <a href="EXAMPLES_md.html">EXAMPLES.md</a>.</p>
|
|
68
|
+
|
|
67
69
|
<h1 id="label-Use+case">Use case</h1>
|
|
68
70
|
|
|
69
71
|
<p>Typically, a Rails application consists of three kinds of state:</p>
|
|
@@ -144,8 +146,14 @@
|
|
|
144
146
|
<pre class="code ruby"><code class="ruby"><span class='comment'># Retrieve all user roles:
|
|
145
147
|
</span><span class='const'>Role</span><span class='period'>.</span><span class='id identifier rubyid_all'>all</span>
|
|
146
148
|
|
|
147
|
-
<span class='comment'># Retrieve a specific role
|
|
149
|
+
<span class='comment'># Retrieve a specific role. `find` accepts a String, a Symbol, or `nil` (returns nil).
|
|
148
150
|
</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>
|
|
151
|
+
<span class='const'>Role</span><span class='period'>.</span><span class='id identifier rubyid_find'>find</span><span class='lparen'>(</span><span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>guest</span><span class='tstring_end'>'</span></span><span class='rparen'>)</span><span class='period'>.</span><span class='id identifier rubyid_privilege_level'>privilege_level</span> <span class='comment'># equivalent
|
|
152
|
+
</span>
|
|
153
|
+
<span class='comment'># Assignment accepts a String, Symbol, or Anchormodel instance:
|
|
154
|
+
</span><span class='ivar'>@user</span><span class='period'>.</span><span class='id identifier rubyid_role'>role</span> <span class='op'>=</span> <span class='tstring'><span class='tstring_beg'>'</span><span class='tstring_content'>admin</span><span class='tstring_end'>'</span></span>
|
|
155
|
+
<span class='ivar'>@user</span><span class='period'>.</span><span class='id identifier rubyid_role'>role</span> <span class='op'>=</span> <span class='symbol'>:admin</span>
|
|
156
|
+
<span class='ivar'>@user</span><span class='period'>.</span><span class='id identifier rubyid_role'>role</span> <span class='op'>=</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'>:admin</span><span class='rparen'>)</span>
|
|
149
157
|
|
|
150
158
|
<span class='comment'># Implement a Rails helper that makes sure users can only edit other users that have a lower privilege level than themselves
|
|
151
159
|
</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>
|
|
@@ -159,6 +167,19 @@
|
|
|
159
167
|
</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)
|
|
160
168
|
</span></code></pre>
|
|
161
169
|
|
|
170
|
+
<h2 id="label-Error+handling">Error handling</h2>
|
|
171
|
+
|
|
172
|
+
<p>Anchormodel raises <code>Anchormodel::InvalidKey</code> whenever an unknown key is supplied — from <code>find</code>, from attribute writers, and from the bulk-key scopes shown below:</p>
|
|
173
|
+
|
|
174
|
+
<pre class="code ruby"><code class="ruby"><span class='kw'>begin</span>
|
|
175
|
+
<span class='const'>Role</span><span class='period'>.</span><span class='id identifier rubyid_find'>find</span><span class='lparen'>(</span><span class='symbol'>:does_not_exist</span><span class='rparen'>)</span>
|
|
176
|
+
<span class='kw'>rescue</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="Anchormodel/InvalidKey.html" title="Anchormodel::InvalidKey (class)">InvalidKey</a></span></span> <span class='op'>=></span> <span class='id identifier rubyid_e'>e</span>
|
|
177
|
+
<span class='comment'># e.message: "Retrieved undefined anchor model key :does_not_exist for Role."
|
|
178
|
+
</span><span class='kw'>end</span>
|
|
179
|
+
</code></pre>
|
|
180
|
+
|
|
181
|
+
<p><code>Anchormodel::InvalidKey</code> inherits from <code>RuntimeError</code>, so existing <code>rescue RuntimeError</code> blocks remain compatible while allowing the narrower <code>rescue Anchormodel::InvalidKey</code>.</p>
|
|
182
|
+
|
|
162
183
|
<p>Your form could look something like this:</p>
|
|
163
184
|
|
|
164
185
|
<pre class="code ruby"><code class="ruby"><%= form_with(model: user) do |form| %>
|
|
@@ -302,6 +323,23 @@
|
|
|
302
323
|
|
|
303
324
|
<p>Note that no other methods of Set are overwritten at this point - if you use any other methods mutating the underlying Set, your changes will not be applied.</p>
|
|
304
325
|
|
|
326
|
+
<h2 id="label-Querying+a+collection+of+Anchormodels">Querying a collection of Anchormodels</h2>
|
|
327
|
+
|
|
328
|
+
<p>Because keys are stored as a CSV string in a single column, the standard Rails idiom <code>Model.where(col: array)</code> does <strong>not</strong> work for <code>belongs_to_anchormodels</code> attributes — it compiles to an <code>IN (...)</code> clause that compares against the full column value (e.g. <code>"cat,dog"</code>) rather than the individual entries.</p>
|
|
329
|
+
|
|
330
|
+
<p>Anchormodel provides two helper scopes for bulk-key queries:</p>
|
|
331
|
+
|
|
332
|
+
<pre class="code ruby"><code class="ruby"><span class='comment'># Users that hold at least one of the given keys
|
|
333
|
+
</span><span class='const'>User</span><span class='period'>.</span><span class='id identifier rubyid_with_any_animals'>with_any_animals</span><span class='lparen'>(</span><span class='symbol'>:cat</span><span class='comma'>,</span> <span class='symbol'>:dog</span><span class='rparen'>)</span>
|
|
334
|
+
|
|
335
|
+
<span class='comment'># Users that hold every given key
|
|
336
|
+
</span><span class='const'>User</span><span class='period'>.</span><span class='id identifier rubyid_with_all_animals'>with_all_animals</span><span class='lparen'>(</span><span class='symbol'>:cat</span><span class='comma'>,</span> <span class='symbol'>:dog</span><span class='rparen'>)</span>
|
|
337
|
+
</code></pre>
|
|
338
|
+
|
|
339
|
+
<p>Both scopes accept <code>String</code>, <code>Symbol</code>, or <code>Anchormodel</code> instances (and nested arrays), and raise <code>Anchormodel::InvalidKey</code> on invalid keys. They are always defined for every <code>belongs_to_anchormodels</code> attribute (independent of the <code>model_scopes</code> setting), named <code>with_any_<attribute_name></code> / <code>with_all_<attribute_name></code>.</p>
|
|
340
|
+
|
|
341
|
+
<p>For a single key, the per-key scope generated by <code>model_scopes</code> (e.g. <code>User.cat</code>) is the most concise option.</p>
|
|
342
|
+
|
|
305
343
|
<h2 id="label-Basic+rails+form+for+a+collection+of+Anchormodels">Basic rails form for a collection of Anchormodels</h2>
|
|
306
344
|
|
|
307
345
|
<pre class="code ruby"><code class="ruby"><%= form_with(model: user) do |form| %>
|
|
@@ -339,7 +377,7 @@
|
|
|
339
377
|
</div></div>
|
|
340
378
|
|
|
341
379
|
<div id="footer">
|
|
342
|
-
Generated on Wed May 13
|
|
380
|
+
Generated on Wed May 13 15:48:24 2026 by
|
|
343
381
|
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
|
344
382
|
0.9.28 (ruby-3.3.5).
|
|
345
383
|
</div>
|