anchormodel 0.1.0 → 0.1.1
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/CHANGELOG.md +6 -0
- data/Gemfile.lock +5 -5
- data/README.md +88 -4
- data/anchormodel.gemspec +4 -4
- data/bin/rails +7 -0
- data/doc/Anchormodel/ActiveModelTypeValue.html +5 -5
- data/doc/Anchormodel/Attribute.html +60 -63
- data/doc/Anchormodel/ModelMixin.html +178 -14
- data/doc/Anchormodel/Version.html +4 -4
- data/doc/Anchormodel.html +28 -18
- data/doc/_index.html +1 -1
- data/doc/file.README.html +91 -9
- data/doc/index.html +91 -9
- data/doc/method_list.html +1 -1
- data/doc/top-level-namespace.html +1 -1
- 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 +1 -1
- data/lib/anchormodel.rb +5 -0
- data/test/active_record_model/user_test.rb +65 -1
- data/test/dummy/app/models/user.rb +3 -1
- data/test/dummy/db/migrate/20230107173151_create_users.rb +2 -0
- data/test/dummy/db/schema.rb +3 -1
- metadata +3 -2
data/doc/index.html
CHANGED
@@ -89,7 +89,14 @@
|
|
89
89
|
|
90
90
|
<p>This is why Anchormodel is strictly relying on String keys corresponding to the entries of an Anchormodel.</p>
|
91
91
|
|
92
|
-
<h1 id="label-
|
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>
|
98
|
+
|
99
|
+
<h1 id="label-Basic+example">Basic example</h1>
|
93
100
|
|
94
101
|
<p><code>app/anchormodels/role.rb</code>:</p>
|
95
102
|
|
@@ -116,7 +123,11 @@
|
|
116
123
|
|
117
124
|
<pre class="code ruby"><code class="ruby"><span class='comment'># The DB table `users` must have a String column `users.role`
|
118
125
|
</span><span class='kw'>class</span> <span class='const'>User</span> <span class='op'><</span> <span class='const'>ApplicationRecord</span>
|
119
|
-
<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>
|
120
131
|
<span class='kw'>end</span>
|
121
132
|
</code></pre>
|
122
133
|
|
@@ -135,18 +146,89 @@
|
|
135
146
|
|
136
147
|
<span class='comment'># Pretty print a user's role, e.g. using the Rails FastGettext gem:
|
137
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>
|
138
|
-
</code></pre>
|
139
149
|
|
140
|
-
<
|
141
|
-
|
142
|
-
|
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>
|
143
159
|
</li><li>
|
144
|
-
<p>
|
145
|
-
</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>
|
218
|
+
</code></pre>
|
219
|
+
|
220
|
+
<h2 id="label-Having+multiple+attributes+to+the+same+Anchormodel">Having multiple attributes to the same Anchormodel</h2>
|
221
|
+
|
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>
|
146
228
|
</div></div>
|
147
229
|
|
148
230
|
<div id="footer">
|
149
|
-
Generated on
|
231
|
+
Generated on Tue Jan 24 20:27:58 2023 by
|
150
232
|
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
151
233
|
0.9.28 (ruby-3.1.3).
|
152
234
|
</div>
|
data/doc/method_list.html
CHANGED
@@ -62,7 +62,7 @@
|
|
62
62
|
|
63
63
|
<li class="odd ">
|
64
64
|
<div class="item">
|
65
|
-
<span class='object_link'><a href="Anchormodel/Attribute.html#
|
65
|
+
<span class='object_link'><a href="Anchormodel/Attribute.html#anchormodel_class-instance_method" title="Anchormodel::Attribute#anchormodel_class (method)">#anchormodel_class</a></span>
|
66
66
|
<small>Anchormodel::Attribute</small>
|
67
67
|
</div>
|
68
68
|
</li>
|
@@ -100,7 +100,7 @@
|
|
100
100
|
</div>
|
101
101
|
|
102
102
|
<div id="footer">
|
103
|
-
Generated on
|
103
|
+
Generated on Tue Jan 24 20:27:59 2023 by
|
104
104
|
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
105
105
|
0.9.28 (ruby-3.1.3).
|
106
106
|
</div>
|
@@ -13,11 +13,11 @@ class Anchormodel::ActiveModelTypeValue < ActiveModel::Type::Value
|
|
13
13
|
def serialize(value)
|
14
14
|
return case value
|
15
15
|
when Symbol, String
|
16
|
-
unless @attribute.
|
16
|
+
unless @attribute.anchormodel_class.valid_keys.include?(value.to_sym)
|
17
17
|
fail("Attempt to set #{@attribute.attribute_name} to unsupported key #{value.inspect}.")
|
18
18
|
end
|
19
19
|
value.to_s
|
20
|
-
when @attribute.
|
20
|
+
when @attribute.anchormodel_class
|
21
21
|
value.key.to_s
|
22
22
|
when nil
|
23
23
|
nil
|
@@ -27,8 +27,8 @@ class Anchormodel::ActiveModelTypeValue < ActiveModel::Type::Value
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def deserialize(value)
|
30
|
-
return value if value.is_a?(@attribute.
|
31
|
-
return @attribute.
|
30
|
+
return value if value.is_a?(@attribute.anchormodel_class)
|
31
|
+
return @attribute.anchormodel_class.find(value)
|
32
32
|
end
|
33
33
|
|
34
34
|
def changed?(old_value, new_value, _new_value_before_type_cast)
|
@@ -3,22 +3,17 @@
|
|
3
3
|
# It is instanciated when {Anchormodel::ModelMixin#belongs_to_anchormodel} is used.
|
4
4
|
class Anchormodel::Attribute
|
5
5
|
attr_reader :attribute_name
|
6
|
+
attr_reader :anchormodel_class
|
6
7
|
attr_reader :optional
|
7
8
|
|
8
9
|
# @param model_class [ActiveRecord::Base] The Rails model where {Anchormodel::ModelMixin#belongs_to_anchormodel} is used
|
9
10
|
# @param attribute_name [String,Symbol] The name and database column of the attribute
|
10
|
-
# @param
|
11
|
+
# @param anchormodel_class [Class] Class of the Anchormodel (omit if attribute `:foo_bar` holds an `FooBar`)
|
11
12
|
# @param optional [Boolean] If true, a presence validation is added to the model.
|
12
|
-
def initialize(model_class, attribute_name,
|
13
|
+
def initialize(model_class, attribute_name, anchormodel_class = nil, optional = false)
|
13
14
|
@model_class = model_class
|
14
15
|
@attribute_name = attribute_name.to_sym
|
15
|
-
@
|
16
|
+
@anchormodel_class = anchormodel_class
|
16
17
|
@optional = optional
|
17
18
|
end
|
18
|
-
|
19
|
-
# Getter for the Anchormodel class based on the name passed to the initializer.
|
20
|
-
# We are loading the anchor class lazily, because the model mixin instanciates this statically -> avoid premature anchor class loading
|
21
|
-
def anchor_class
|
22
|
-
@anchor_class ||= @anchor_class_name.constantize
|
23
|
-
end
|
24
19
|
end
|
@@ -11,11 +11,24 @@ module Anchormodel::ModelMixin
|
|
11
11
|
# Creates an attribute linking to an Anchormodel. The attribute should be
|
12
12
|
# present in the DB and the column should be named the same as `attribute_name.`
|
13
13
|
# @param attribute_name [String,Symbol] The name and database column of the attribute
|
14
|
-
# @param
|
14
|
+
# @param anchormodel_class [Class] Class of the Anchormodel (omit if attribute `:foo_bar` holds a `FooBar`)
|
15
15
|
# @param optional [Boolean] If true, a presence validation is added to the model.
|
16
|
-
|
16
|
+
# @param model_readers [Boolean] If true, the model is given an ActiveRecord::Enum style method `my_model.my_key?` reader for each key in the anchormodel
|
17
|
+
# @param model_writers [Boolean] If true, the model is given an ActiveRecord::Enum style method `my_model.my_key!` writer for each key in the anchormodel
|
18
|
+
# @param model_scopes [Boolean] If true, the model is given an ActiveRecord::Enum style scope `MyModel.mykey` for each key in the anchormodel
|
19
|
+
# @param model_methods [Boolean, NilClass] If non-nil, this mass-assigns and overrides `model_readers`, `model_writers` and `model_scopes`
|
20
|
+
def belongs_to_anchormodel(attribute_name, anchormodel_class = nil, optional: false, model_readers: true,
|
21
|
+
model_writers: true, model_scopes: true, model_methods: nil)
|
22
|
+
anchormodel_class ||= attribute_name.to_s.classify.constantize
|
17
23
|
attribute_name = attribute_name.to_sym
|
18
|
-
attribute = Anchormodel::Attribute.new(self, attribute_name,
|
24
|
+
attribute = Anchormodel::Attribute.new(self, attribute_name, anchormodel_class, optional)
|
25
|
+
|
26
|
+
# Mass configurations if model_methods was specfied
|
27
|
+
unless model_methods.nil?
|
28
|
+
model_readers = model_methods
|
29
|
+
model_writers = model_methods
|
30
|
+
model_scopes = model_methods
|
31
|
+
end
|
19
32
|
|
20
33
|
# Register attribute
|
21
34
|
self.anchormodel_attributes = anchormodel_attributes.merge({ attribute_name => attribute }).freeze
|
@@ -41,6 +54,43 @@ module Anchormodel::ModelMixin
|
|
41
54
|
|
42
55
|
# Supply serializer and deserializer
|
43
56
|
attribute attribute_name, active_model_type_value
|
57
|
+
|
58
|
+
# Create ActiveRecord::Enum style reader directly in the model if asked to do so
|
59
|
+
# For a model User with anchormodel Role with keys :admin and :guest, this creates user.admin? and user.guest? (returning true iff role is admin/guest)
|
60
|
+
if model_readers
|
61
|
+
anchormodel_class.all.each do |entry|
|
62
|
+
if respond_to?(:"#{entry.key}?")
|
63
|
+
fail("Anchormodel reader #{entry.key}? already defined for #{self}, add `model_readers: false` to `belongs_to_anchormodel :#{attribute_name}`.")
|
64
|
+
end
|
65
|
+
define_method(:"#{entry.key}?") do
|
66
|
+
public_send(attribute_name.to_s) == entry
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# Create ActiveRecord::Enum style writer directly in the model if asked to do so
|
72
|
+
# 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)
|
73
|
+
if model_writers
|
74
|
+
anchormodel_class.all.each do |entry|
|
75
|
+
if respond_to?(:"#{entry.key}!")
|
76
|
+
fail("Anchormodel writer #{entry.key}! already defined for #{self}, add `model_writers: false` to `belongs_to_anchormodel :#{attribute_name}`.")
|
77
|
+
end
|
78
|
+
define_method(:"#{entry.key}!") do
|
79
|
+
public_send(:"#{attribute_name.to_s}=", entry)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# Create ActiveRecord::Enum style scope directly in the model class if asked to do so
|
85
|
+
# 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)
|
86
|
+
if model_scopes
|
87
|
+
anchormodel_class.all.each do |entry|
|
88
|
+
if respond_to?(entry.key)
|
89
|
+
fail("Anchormodel scope #{entry.key} already defined for #{self}, add `model_scopes: false` to `belongs_to_anchormodel :#{attribute_name}`.")
|
90
|
+
end
|
91
|
+
scope(entry.key, ->{where(attribute_name => entry.key)})
|
92
|
+
end
|
93
|
+
end
|
44
94
|
end
|
45
95
|
end
|
46
96
|
end
|
data/lib/anchormodel/version.rb
CHANGED
data/lib/anchormodel.rb
CHANGED
@@ -1,6 +1,10 @@
|
|
1
1
|
class UserTest < Minitest::Test
|
2
2
|
def setup; end
|
3
3
|
|
4
|
+
def teardown
|
5
|
+
User.destroy_all
|
6
|
+
end
|
7
|
+
|
4
8
|
def test_retrieval
|
5
9
|
assert_equal Role.find(:guest), Role.find('guest')
|
6
10
|
end
|
@@ -17,7 +21,11 @@ class UserTest < Minitest::Test
|
|
17
21
|
)
|
18
22
|
end
|
19
23
|
|
20
|
-
def
|
24
|
+
def test_missing_key
|
25
|
+
assert_raises { Role.find(:does_not_exist) }
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_basic_setters_and_getters
|
21
29
|
u = User.create!(role: 'guest', locale: 'de') # String assignment
|
22
30
|
assert_equal Role.find(:guest), u.role
|
23
31
|
assert_equal Locale.find(:de), u.locale
|
@@ -48,4 +56,60 @@ class UserTest < Minitest::Test
|
|
48
56
|
assert_equal(0, Role.find(:moderator) <=> Role.find(:moderator))
|
49
57
|
assert Role.find(:moderator) < Role.find(:admin)
|
50
58
|
end
|
59
|
+
|
60
|
+
def test_presence_validation
|
61
|
+
valentine = User.new
|
62
|
+
assert_raises(ActiveRecord::RecordInvalid) { valentine.save! }
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_alternative_column_name
|
66
|
+
ben = User.create!(
|
67
|
+
role: Role.find(:moderator),
|
68
|
+
secondary_role: Role.find(:admin),
|
69
|
+
locale: Locale.find(:de)
|
70
|
+
)
|
71
|
+
assert_equal(Role.find(:moderator), ben.role)
|
72
|
+
assert_equal(Role.find(:admin), ben.secondary_role)
|
73
|
+
assert_equal(Locale.find(:de), ben.locale)
|
74
|
+
end
|
75
|
+
|
76
|
+
def test_optional_attribute
|
77
|
+
jenny = User.create!(role: :admin, locale: :en)
|
78
|
+
assert_nil jenny.secondary_role
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_model_readers_and_writers
|
82
|
+
pia = User.new
|
83
|
+
pia.admin!
|
84
|
+
assert_equal true, pia.admin?
|
85
|
+
assert_equal false, pia.guest?
|
86
|
+
assert_equal Role.find(:admin), pia.role
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_model_scopes
|
90
|
+
User.create!(role: :admin, locale: :en)
|
91
|
+
User.create!(role: :admin, locale: :en)
|
92
|
+
User.create!(role: :moderator, locale: :en)
|
93
|
+
assert_equal 2, User.admin.count
|
94
|
+
assert_equal 1, User.moderator.count
|
95
|
+
assert_equal 0, User.guest.count
|
96
|
+
end
|
97
|
+
|
98
|
+
def test_model_readers_writers_with_different_class_name
|
99
|
+
pia = User.new(locale: :en)
|
100
|
+
pia.de!
|
101
|
+
assert_equal true, pia.de?
|
102
|
+
assert_equal false, pia.fr?
|
103
|
+
assert_equal Locale.find(:de), pia.preferred_locale
|
104
|
+
assert_equal Locale.find(:en), pia.locale
|
105
|
+
end
|
106
|
+
|
107
|
+
def test_model_scopes_with_different_class_name
|
108
|
+
User.create!(role: :admin, locale: :en, preferred_locale: :de)
|
109
|
+
User.create!(role: :admin, locale: :en, preferred_locale: :de)
|
110
|
+
User.create!(role: :admin, locale: :en, preferred_locale: :fr)
|
111
|
+
assert_equal 2, User.de.count
|
112
|
+
assert_equal 1, User.fr.count
|
113
|
+
assert_equal 0, User.en.count
|
114
|
+
end
|
51
115
|
end
|
@@ -1,4 +1,6 @@
|
|
1
1
|
class User < ApplicationRecord
|
2
2
|
belongs_to_anchormodel :role
|
3
|
-
belongs_to_anchormodel :
|
3
|
+
belongs_to_anchormodel :secondary_role, Role, optional: true, model_readers: false, model_writers: false, model_scopes: false
|
4
|
+
belongs_to_anchormodel :locale, model_methods: false
|
5
|
+
belongs_to_anchormodel :preferred_locale, Locale
|
4
6
|
end
|
data/test/dummy/db/schema.rb
CHANGED
@@ -10,12 +10,14 @@
|
|
10
10
|
#
|
11
11
|
# It's strongly recommended that you check this file into your version control system.
|
12
12
|
|
13
|
-
ActiveRecord::Schema[7.0].define(version:
|
13
|
+
ActiveRecord::Schema[7.0].define(version: 2023_01_24_084241) do
|
14
14
|
create_table "users", force: :cascade do |t|
|
15
15
|
t.string "role"
|
16
16
|
t.string "locale"
|
17
17
|
t.datetime "created_at", null: false
|
18
18
|
t.datetime "updated_at", null: false
|
19
|
+
t.string "secondary_role"
|
20
|
+
t.string "preferred_locale", default: "en", null: false
|
19
21
|
end
|
20
22
|
|
21
23
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: anchormodel
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sandro Kalbermatter
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-01-
|
11
|
+
date: 2023-01-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -166,6 +166,7 @@ files:
|
|
166
166
|
- README.md
|
167
167
|
- Rakefile
|
168
168
|
- anchormodel.gemspec
|
169
|
+
- bin/rails
|
169
170
|
- doc/Anchormodel.html
|
170
171
|
- doc/Anchormodel/ActiveModelTypeValue.html
|
171
172
|
- doc/Anchormodel/Attribute.html
|