anchormodel 0.2.6 → 0.3.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/.gitignore +3 -1
- data/CHANGELOG.md +11 -0
- data/Gemfile.lock +28 -22
- data/README.md +3 -3
- data/VERSION +1 -1
- data/anchormodel.gemspec +3 -3
- data/doc/Anchormodel/ActiveModelTypeValueMulti.html +3 -3
- data/doc/Anchormodel/ActiveModelTypeValueSingle.html +18 -54
- data/doc/Anchormodel/Attribute.html +3 -3
- data/doc/Anchormodel/ModelMixin.html +3 -3
- data/doc/Anchormodel/SimpleFormInputs/Helpers/AnchormodelInputsCommon.html +3 -3
- data/doc/Anchormodel/SimpleFormInputs/Helpers.html +3 -3
- data/doc/Anchormodel/SimpleFormInputs.html +3 -3
- data/doc/Anchormodel/Util.html +3 -3
- data/doc/Anchormodel/Version.html +3 -3
- data/doc/Anchormodel.html +22 -20
- data/doc/AnchormodelCheckBoxesInput.html +3 -3
- data/doc/AnchormodelGenerator.html +3 -3
- data/doc/AnchormodelInput.html +3 -3
- data/doc/AnchormodelRadioButtonsInput.html +3 -3
- data/doc/_index.html +4 -4
- data/doc/class_list.html +3 -6
- data/doc/css/full_list.css +3 -3
- data/doc/css/style.css +0 -6
- data/doc/file.README.html +5 -5
- data/doc/file_list.html +2 -5
- data/doc/frames.html +5 -10
- data/doc/index.html +5 -5
- data/doc/js/app.js +264 -294
- data/doc/js/full_list.js +4 -30
- data/doc/method_list.html +2 -5
- data/doc/top-level-namespace.html +3 -3
- data/lib/anchormodel/active_model_type_value_single.rb +19 -9
- data/lib/anchormodel.rb +1 -0
- data/test/active_record_model/user_test.rb +39 -0
- metadata +2 -2
data/doc/js/full_list.js
CHANGED
|
@@ -62,25 +62,8 @@ function enableToggles() {
|
|
|
62
62
|
evt.stopPropagation();
|
|
63
63
|
evt.preventDefault();
|
|
64
64
|
$(this).parent().parent().toggleClass('collapsed');
|
|
65
|
-
$(this).attr('aria-expanded', function (i, attr) {
|
|
66
|
-
return attr == 'true' ? 'false' : 'true'
|
|
67
|
-
});
|
|
68
65
|
highlight();
|
|
69
66
|
});
|
|
70
|
-
|
|
71
|
-
// navigation of nested classes using keyboard
|
|
72
|
-
$('#full_list a.toggle').on('keypress',function(evt) {
|
|
73
|
-
// enter key is pressed
|
|
74
|
-
if (evt.which == 13) {
|
|
75
|
-
evt.stopPropagation();
|
|
76
|
-
evt.preventDefault();
|
|
77
|
-
$(this).parent().parent().toggleClass('collapsed');
|
|
78
|
-
$(this).attr('aria-expanded', function (i, attr) {
|
|
79
|
-
return attr == 'true' ? 'false' : 'true'
|
|
80
|
-
});
|
|
81
|
-
highlight();
|
|
82
|
-
}
|
|
83
|
-
});
|
|
84
67
|
}
|
|
85
68
|
|
|
86
69
|
function populateSearchCache() {
|
|
@@ -108,7 +91,7 @@ function enableSearch() {
|
|
|
108
91
|
}
|
|
109
92
|
});
|
|
110
93
|
|
|
111
|
-
$('#full_list').after("<div id='noresults'
|
|
94
|
+
$('#full_list').after("<div id='noresults' style='display:none'></div>");
|
|
112
95
|
}
|
|
113
96
|
|
|
114
97
|
function ignoredKeyPress(event) {
|
|
@@ -171,14 +154,11 @@ function partialSearch(searchString, offset) {
|
|
|
171
154
|
function searchDone() {
|
|
172
155
|
searchTimeout = null;
|
|
173
156
|
highlight();
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
$('#noresults').text('No results were found.');
|
|
157
|
+
if ($('#full_list li:visible').size() === 0) {
|
|
158
|
+
$('#noresults').text('No results were found.').hide().fadeIn();
|
|
177
159
|
} else {
|
|
178
|
-
|
|
179
|
-
$('#noresults').text('There are ' + found + ' results.');
|
|
160
|
+
$('#noresults').text('').hide();
|
|
180
161
|
}
|
|
181
|
-
$('#noresults').show();
|
|
182
162
|
$('#content').removeClass('insearch');
|
|
183
163
|
}
|
|
184
164
|
|
|
@@ -208,12 +188,6 @@ function expandTo(path) {
|
|
|
208
188
|
$target.addClass('clicked');
|
|
209
189
|
$target.removeClass('collapsed');
|
|
210
190
|
$target.parentsUntil('#full_list', 'li').removeClass('collapsed');
|
|
211
|
-
|
|
212
|
-
$target.find('a.toggle').attr('aria-expanded', 'true')
|
|
213
|
-
$target.parentsUntil('#full_list', 'li').each(function(i, el) {
|
|
214
|
-
$(el).find('> div > a.toggle').attr('aria-expanded', 'true');
|
|
215
|
-
});
|
|
216
|
-
|
|
217
191
|
if($target[0]) {
|
|
218
192
|
window.scrollTo(window.scrollX, $target.offset().top - 250);
|
|
219
193
|
highlight();
|
data/doc/method_list.html
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<!DOCTYPE html>
|
|
2
|
-
<html
|
|
2
|
+
<html>
|
|
3
3
|
<head>
|
|
4
4
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
5
5
|
<meta charset="utf-8" />
|
|
@@ -38,10 +38,7 @@
|
|
|
38
38
|
|
|
39
39
|
</div>
|
|
40
40
|
|
|
41
|
-
<div id="search">
|
|
42
|
-
<label for="search-class">Search:</label>
|
|
43
|
-
<input id="search-class" type="text" />
|
|
44
|
-
</div>
|
|
41
|
+
<div id="search">Search: <input type="text" /></div>
|
|
45
42
|
</div>
|
|
46
43
|
|
|
47
44
|
<ul id="full_list" class="method">
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
<title>
|
|
7
7
|
Top Level Namespace
|
|
8
8
|
|
|
9
|
-
— Documentation by YARD 0.9.
|
|
9
|
+
— Documentation by YARD 0.9.28
|
|
10
10
|
|
|
11
11
|
</title>
|
|
12
12
|
|
|
@@ -100,9 +100,9 @@
|
|
|
100
100
|
</div>
|
|
101
101
|
|
|
102
102
|
<div id="footer">
|
|
103
|
-
Generated on
|
|
103
|
+
Generated on Wed May 13 11:46:10 2026 by
|
|
104
104
|
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
|
105
|
-
0.9.
|
|
105
|
+
0.9.28 (ruby-3.3.5).
|
|
106
106
|
</div>
|
|
107
107
|
|
|
108
108
|
</div>
|
|
@@ -20,6 +20,23 @@ class Anchormodel::ActiveModelTypeValueSingle < ActiveModel::Type::Value
|
|
|
20
20
|
|
|
21
21
|
# This converts an Anchormodel instance to string for DB
|
|
22
22
|
def serialize(value)
|
|
23
|
+
return value.map { |v| serialize_scalar(v) } if value.is_a?(Array)
|
|
24
|
+
serialize_scalar(value)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def serializable?(value)
|
|
28
|
+
return value.all? { |v| scalar_serializable?(v) } if value.is_a?(Array)
|
|
29
|
+
scalar_serializable?(value)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def changed_in_place?(raw_old_value, value)
|
|
33
|
+
old_value = deserialize(raw_old_value)
|
|
34
|
+
old_value != value
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
private
|
|
38
|
+
|
|
39
|
+
def serialize_scalar(value)
|
|
23
40
|
value = value.presence
|
|
24
41
|
return case value
|
|
25
42
|
when Symbol, String
|
|
@@ -36,19 +53,12 @@ class Anchormodel::ActiveModelTypeValueSingle < ActiveModel::Type::Value
|
|
|
36
53
|
end
|
|
37
54
|
end
|
|
38
55
|
|
|
39
|
-
def
|
|
56
|
+
def scalar_serializable?(value)
|
|
40
57
|
return case value
|
|
41
|
-
when Symbol, String
|
|
42
|
-
@attribute.anchormodel_class.valid_keys.exclude?(value.to_sym)
|
|
43
|
-
when nil, @attribute.anchormodel_class
|
|
58
|
+
when Symbol, String, nil, @attribute.anchormodel_class
|
|
44
59
|
true
|
|
45
60
|
else
|
|
46
61
|
false
|
|
47
62
|
end
|
|
48
63
|
end
|
|
49
|
-
|
|
50
|
-
def changed_in_place?(raw_old_value, value)
|
|
51
|
-
old_value = deserialize(raw_old_value)
|
|
52
|
-
old_value != value
|
|
53
|
-
end
|
|
54
64
|
end
|
data/lib/anchormodel.rb
CHANGED
|
@@ -86,6 +86,45 @@ class UserTest < Minitest::Test
|
|
|
86
86
|
assert_equal 0, User.guest.count
|
|
87
87
|
end
|
|
88
88
|
|
|
89
|
+
# Regression: `where(anchormodel_col: %w[a b])` used to collapse to `IN (NULL)`
|
|
90
|
+
# because Single#serialize lacked Array handling. See memory `array-where-collapses-to-null`.
|
|
91
|
+
def test_where_with_array_of_keys
|
|
92
|
+
User.create!(role: :admin, locale: :en)
|
|
93
|
+
User.create!(role: :moderator, locale: :en)
|
|
94
|
+
User.create!(role: :guest, locale: :en)
|
|
95
|
+
|
|
96
|
+
sql = User.where(role: %w[admin moderator]).to_sql
|
|
97
|
+
assert_match(/admin/, sql)
|
|
98
|
+
assert_match(/moderator/, sql)
|
|
99
|
+
refute_match(/IN \(NULL\)/i, sql) # rubocop:disable Rails/RefuteMethods
|
|
100
|
+
|
|
101
|
+
assert_equal 2, User.where(role: %w[admin moderator]).count
|
|
102
|
+
assert_equal 2, User.where(role: %i[admin moderator]).count
|
|
103
|
+
assert_equal(
|
|
104
|
+
2,
|
|
105
|
+
User.where(role: [Role.find(:admin), Role.find(:moderator)]).count
|
|
106
|
+
)
|
|
107
|
+
assert_equal 1, User.where.not(role: %w[admin moderator]).count
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def test_where_with_array_of_invalid_keys_raises
|
|
111
|
+
assert_raises(RuntimeError) { User.where(role: %w[admin nope]).to_a }
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# Direct probe on `serializable?` — guards against re-introducing the inverted
|
|
115
|
+
# `exclude?` logic that silently dropped valid keys from `HomogeneousIn` binds.
|
|
116
|
+
def test_serializable_predicate
|
|
117
|
+
type = User.type_for_attribute(:role)
|
|
118
|
+
assert type.serializable?('admin')
|
|
119
|
+
assert type.serializable?(:admin)
|
|
120
|
+
assert type.serializable?(Role.find(:admin))
|
|
121
|
+
assert type.serializable?(nil)
|
|
122
|
+
assert type.serializable?(%w[admin guest])
|
|
123
|
+
assert type.serializable?([:admin, Role.find(:guest)])
|
|
124
|
+
refute type.serializable?(42) # rubocop:disable Rails/RefuteMethods
|
|
125
|
+
refute type.serializable?([42]) # rubocop:disable Rails/RefuteMethods
|
|
126
|
+
end
|
|
127
|
+
|
|
89
128
|
def test_model_readers_writers_with_different_class_name
|
|
90
129
|
pia = User.new(locale: :en)
|
|
91
130
|
pia.de!
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: anchormodel
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Sandro Kalbermatter
|
|
@@ -263,7 +263,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
263
263
|
- !ruby/object:Gem::Version
|
|
264
264
|
version: '0'
|
|
265
265
|
requirements: []
|
|
266
|
-
rubygems_version:
|
|
266
|
+
rubygems_version: 4.0.11
|
|
267
267
|
specification_version: 4
|
|
268
268
|
summary: Bringing object-oriented programming to Rails enums
|
|
269
269
|
test_files: []
|