appquery 0.7.0.rc3 → 0.7.0.rc5
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/.yard/templates/default/fulldoc/html/js/app.js +345 -0
- data/lib/app_query/base_query.rb +22 -20
- data/lib/app_query/mappable.rb +24 -3
- data/lib/app_query/paginatable.rb +15 -2
- data/lib/app_query/version.rb +1 -1
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f0a7427b588822074b0d97fa98f7008bd4a66a9630619e425421341ad5d74b2d
|
|
4
|
+
data.tar.gz: bfc1eead06bc7f5c8044694adb349260bab5ce8b0f11d8918fa1e068b736a2ac
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9fd7aad6bcc1ec6a05f2fa2bdcebfd2c23b46d48ab9faa3b166651c2d680da82cb4ebee3faa8fcc7d20690777e2342943bbb01180eefab0bcf75ae7ca820745e
|
|
7
|
+
data.tar.gz: c3d0cfb70e26b846dadc3b0dc89b1cbdaa6aa5d9de7a5b06cdee583ccd9fb7fd517aa128a8dda341eed92f3e615f501986b06b778c71642810aae485bcc5ed10
|
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
// Simplified YARD app.js - disabled SPA navigation in favor of regular links
|
|
2
|
+
// The original SPA navigation was broken for nested pages
|
|
3
|
+
|
|
4
|
+
window.__app = function () {
|
|
5
|
+
var localStorage = {},
|
|
6
|
+
sessionStorage = {};
|
|
7
|
+
try {
|
|
8
|
+
localStorage = window.localStorage;
|
|
9
|
+
} catch (e) {}
|
|
10
|
+
try {
|
|
11
|
+
sessionStorage = window.sessionStorage;
|
|
12
|
+
} catch (e) {}
|
|
13
|
+
|
|
14
|
+
function createSourceLinks() {
|
|
15
|
+
$(".method_details_list .source_code").before(
|
|
16
|
+
"<span class='showSource'>[<a href='#' class='toggleSource'>View source</a>]</span>"
|
|
17
|
+
);
|
|
18
|
+
$(".toggleSource").toggle(
|
|
19
|
+
function () {
|
|
20
|
+
$(this).parent().nextAll(".source_code").slideDown(100);
|
|
21
|
+
$(this).text("Hide source");
|
|
22
|
+
},
|
|
23
|
+
function () {
|
|
24
|
+
$(this).parent().nextAll(".source_code").slideUp(100);
|
|
25
|
+
$(this).text("View source");
|
|
26
|
+
}
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function createDefineLinks() {
|
|
31
|
+
var tHeight = 0;
|
|
32
|
+
$(".defines").after(" <a href='#' class='toggleDefines'>more...</a>");
|
|
33
|
+
$(".toggleDefines").toggle(
|
|
34
|
+
function () {
|
|
35
|
+
tHeight = $(this).parent().prev().height();
|
|
36
|
+
$(this).prev().css("display", "inline");
|
|
37
|
+
$(this).parent().prev().height($(this).parent().height());
|
|
38
|
+
$(this).text("(less)");
|
|
39
|
+
},
|
|
40
|
+
function () {
|
|
41
|
+
$(this).prev().hide();
|
|
42
|
+
$(this).parent().prev().height(tHeight);
|
|
43
|
+
$(this).text("more...");
|
|
44
|
+
}
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function createFullTreeLinks() {
|
|
49
|
+
var tHeight = 0;
|
|
50
|
+
$(".inheritanceTree").toggle(
|
|
51
|
+
function () {
|
|
52
|
+
tHeight = $(this).parent().prev().height();
|
|
53
|
+
$(this).parent().toggleClass("showAll");
|
|
54
|
+
$(this).text("(hide)");
|
|
55
|
+
$(this).parent().prev().height($(this).parent().height());
|
|
56
|
+
},
|
|
57
|
+
function () {
|
|
58
|
+
$(this).parent().toggleClass("showAll");
|
|
59
|
+
$(this).parent().prev().height(tHeight);
|
|
60
|
+
$(this).text("show all");
|
|
61
|
+
}
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function searchFrameButtons() {
|
|
66
|
+
$(".full_list_link").click(function () {
|
|
67
|
+
toggleSearchFrame(this, $(this).attr("href"));
|
|
68
|
+
return false;
|
|
69
|
+
});
|
|
70
|
+
window.addEventListener("message", function (e) {
|
|
71
|
+
if (e.data === "navEscape") {
|
|
72
|
+
$("#nav").slideUp(100);
|
|
73
|
+
$("#search a").removeClass("active inactive");
|
|
74
|
+
$(window).focus();
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
$(window).resize(function () {
|
|
79
|
+
if ($("#search:visible").length === 0) {
|
|
80
|
+
$("#nav").removeAttr("style");
|
|
81
|
+
$("#search a").removeClass("active inactive");
|
|
82
|
+
$(window).focus();
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function toggleSearchFrame(id, link) {
|
|
88
|
+
var frame = $("#nav");
|
|
89
|
+
$("#search a").removeClass("active").addClass("inactive");
|
|
90
|
+
if (frame.attr("src") === link && frame.css("display") !== "none") {
|
|
91
|
+
frame.slideUp(100);
|
|
92
|
+
$("#search a").removeClass("active inactive");
|
|
93
|
+
} else {
|
|
94
|
+
$(id).addClass("active").removeClass("inactive");
|
|
95
|
+
if (frame.attr("src") !== link) frame.attr("src", link);
|
|
96
|
+
frame.slideDown(100);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function linkSummaries() {
|
|
101
|
+
$(".summary_signature").click(function () {
|
|
102
|
+
document.location = $(this).find("a").attr("href");
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function summaryToggle() {
|
|
107
|
+
$(".summary_toggle").click(function (e) {
|
|
108
|
+
e.preventDefault();
|
|
109
|
+
localStorage.summaryCollapsed = $(this).text();
|
|
110
|
+
$(".summary_toggle").each(function () {
|
|
111
|
+
$(this).text($(this).text() == "collapse" ? "expand" : "collapse");
|
|
112
|
+
var next = $(this).parent().parent().nextAll("ul.summary").first();
|
|
113
|
+
if (next.hasClass("compact")) {
|
|
114
|
+
next.toggle();
|
|
115
|
+
next.nextAll("ul.summary").first().toggle();
|
|
116
|
+
} else if (next.hasClass("summary")) {
|
|
117
|
+
var list = $('<ul class="summary compact" />');
|
|
118
|
+
list.html(next.html());
|
|
119
|
+
list.find(".summary_desc, .note").remove();
|
|
120
|
+
list.find("a").each(function () {
|
|
121
|
+
$(this).html($(this).find("strong").html());
|
|
122
|
+
$(this).parent().html($(this)[0].outerHTML);
|
|
123
|
+
});
|
|
124
|
+
next.before(list);
|
|
125
|
+
next.toggle();
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
return false;
|
|
129
|
+
});
|
|
130
|
+
if (localStorage.summaryCollapsed == "collapse") {
|
|
131
|
+
$(".summary_toggle").first().click();
|
|
132
|
+
} else {
|
|
133
|
+
localStorage.summaryCollapsed = "expand";
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function constantSummaryToggle() {
|
|
138
|
+
$(".constants_summary_toggle").click(function (e) {
|
|
139
|
+
e.preventDefault();
|
|
140
|
+
localStorage.summaryCollapsed = $(this).text();
|
|
141
|
+
$(".constants_summary_toggle").each(function () {
|
|
142
|
+
$(this).text($(this).text() == "collapse" ? "expand" : "collapse");
|
|
143
|
+
var next = $(this).parent().parent().nextAll("dl.constants").first();
|
|
144
|
+
if (next.hasClass("compact")) {
|
|
145
|
+
next.toggle();
|
|
146
|
+
next.nextAll("dl.constants").first().toggle();
|
|
147
|
+
} else if (next.hasClass("constants")) {
|
|
148
|
+
var list = $('<dl class="constants compact" />');
|
|
149
|
+
list.html(next.html());
|
|
150
|
+
list.find("dt").each(function () {
|
|
151
|
+
$(this).addClass("summary_signature");
|
|
152
|
+
$(this).text($(this).text().split("=")[0]);
|
|
153
|
+
if ($(this).has(".deprecated").length) {
|
|
154
|
+
$(this).addClass("deprecated");
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
list.find("pre.code").each(function () {
|
|
158
|
+
var dt_element = $(this).parent().prev();
|
|
159
|
+
var tooltip = $(this).text();
|
|
160
|
+
if (dt_element.hasClass("deprecated")) {
|
|
161
|
+
tooltip = "Deprecated. " + tooltip;
|
|
162
|
+
}
|
|
163
|
+
dt_element.attr("title", tooltip);
|
|
164
|
+
});
|
|
165
|
+
list.find(".docstring, .tags, dd").remove();
|
|
166
|
+
next.before(list);
|
|
167
|
+
next.toggle();
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
return false;
|
|
171
|
+
});
|
|
172
|
+
if (localStorage.summaryCollapsed == "collapse") {
|
|
173
|
+
$(".constants_summary_toggle").first().click();
|
|
174
|
+
} else {
|
|
175
|
+
localStorage.summaryCollapsed = "expand";
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
function generateTOC() {
|
|
180
|
+
if ($("#filecontents").length === 0) return;
|
|
181
|
+
var _toc = $('<ol class="top"></ol>');
|
|
182
|
+
var show = false;
|
|
183
|
+
var toc = _toc;
|
|
184
|
+
var counter = 0;
|
|
185
|
+
var tags = ["h2", "h3", "h4", "h5", "h6"];
|
|
186
|
+
var i;
|
|
187
|
+
var curli;
|
|
188
|
+
if ($("#filecontents h1").length > 1) tags.unshift("h1");
|
|
189
|
+
for (i = 0; i < tags.length; i++) {
|
|
190
|
+
tags[i] = "#filecontents " + tags[i];
|
|
191
|
+
}
|
|
192
|
+
var lastTag = parseInt(tags[0][1], 10);
|
|
193
|
+
$(tags.join(", ")).each(function () {
|
|
194
|
+
if ($(this).parents(".method_details .docstring").length != 0) return;
|
|
195
|
+
if (this.id == "filecontents") return;
|
|
196
|
+
show = true;
|
|
197
|
+
var thisTag = parseInt(this.tagName[1], 10);
|
|
198
|
+
if (this.id.length === 0) {
|
|
199
|
+
var proposedId = $(this).attr("toc-id");
|
|
200
|
+
if (typeof proposedId != "undefined") this.id = proposedId;
|
|
201
|
+
else {
|
|
202
|
+
var proposedId = $(this)
|
|
203
|
+
.text()
|
|
204
|
+
.replace(/[^a-z0-9-]/gi, "_");
|
|
205
|
+
if ($("#" + proposedId).length > 0) {
|
|
206
|
+
proposedId += counter;
|
|
207
|
+
counter++;
|
|
208
|
+
}
|
|
209
|
+
this.id = proposedId;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
if (thisTag > lastTag) {
|
|
213
|
+
for (i = 0; i < thisTag - lastTag; i++) {
|
|
214
|
+
if (typeof curli == "undefined") {
|
|
215
|
+
curli = $("<li/>");
|
|
216
|
+
toc.append(curli);
|
|
217
|
+
}
|
|
218
|
+
toc = $("<ol/>");
|
|
219
|
+
curli.append(toc);
|
|
220
|
+
curli = undefined;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
if (thisTag < lastTag) {
|
|
224
|
+
for (i = 0; i < lastTag - thisTag; i++) {
|
|
225
|
+
toc = toc.parent();
|
|
226
|
+
toc = toc.parent();
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
var title = $(this).attr("toc-title");
|
|
230
|
+
if (typeof title == "undefined") title = $(this).text();
|
|
231
|
+
curli = $('<li><a href="#' + this.id + '">' + title + "</a></li>");
|
|
232
|
+
toc.append(curli);
|
|
233
|
+
lastTag = thisTag;
|
|
234
|
+
});
|
|
235
|
+
if (!show) return;
|
|
236
|
+
html =
|
|
237
|
+
'<div id="toc"><p class="title hide_toc"><a href="#"><strong>Table of Contents</strong></a></p></div>';
|
|
238
|
+
$("#content").prepend(html);
|
|
239
|
+
$("#toc").append(_toc);
|
|
240
|
+
$("#toc .hide_toc").toggle(
|
|
241
|
+
function () {
|
|
242
|
+
$("#toc .top").slideUp("fast");
|
|
243
|
+
$("#toc").toggleClass("hidden");
|
|
244
|
+
$("#toc .title small").toggle();
|
|
245
|
+
},
|
|
246
|
+
function () {
|
|
247
|
+
$("#toc .top").slideDown("fast");
|
|
248
|
+
$("#toc").toggleClass("hidden");
|
|
249
|
+
$("#toc .title small").toggle();
|
|
250
|
+
}
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
function navResizer() {
|
|
255
|
+
const resizer = document.getElementById("resizer");
|
|
256
|
+
resizer.addEventListener(
|
|
257
|
+
"pointerdown",
|
|
258
|
+
function (e) {
|
|
259
|
+
resizer.setPointerCapture(e.pointerId);
|
|
260
|
+
e.preventDefault();
|
|
261
|
+
e.stopPropagation();
|
|
262
|
+
},
|
|
263
|
+
false
|
|
264
|
+
);
|
|
265
|
+
resizer.addEventListener(
|
|
266
|
+
"pointerup",
|
|
267
|
+
function (e) {
|
|
268
|
+
resizer.releasePointerCapture(e.pointerId);
|
|
269
|
+
e.preventDefault();
|
|
270
|
+
e.stopPropagation();
|
|
271
|
+
},
|
|
272
|
+
false
|
|
273
|
+
);
|
|
274
|
+
resizer.addEventListener(
|
|
275
|
+
"pointermove",
|
|
276
|
+
function (e) {
|
|
277
|
+
if ((e.buttons & 1) === 0) {
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
sessionStorage.navWidth = e.pageX.toString();
|
|
282
|
+
$(".nav_wrap").css("width", Math.max(200, e.pageX));
|
|
283
|
+
e.preventDefault();
|
|
284
|
+
e.stopPropagation();
|
|
285
|
+
},
|
|
286
|
+
false
|
|
287
|
+
);
|
|
288
|
+
|
|
289
|
+
if (sessionStorage.navWidth) {
|
|
290
|
+
$(".nav_wrap").css(
|
|
291
|
+
"width",
|
|
292
|
+
Math.max(200, parseInt(sessionStorage.navWidth, 10))
|
|
293
|
+
);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
function navExpander() {
|
|
298
|
+
if (typeof pathId === "undefined") return;
|
|
299
|
+
var done = false,
|
|
300
|
+
timer = setTimeout(postMessage, 500);
|
|
301
|
+
function postMessage() {
|
|
302
|
+
if (done) return;
|
|
303
|
+
clearTimeout(timer);
|
|
304
|
+
var opts = { action: "expand", path: pathId };
|
|
305
|
+
document.getElementById("nav").contentWindow.postMessage(opts, "*");
|
|
306
|
+
done = true;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
function mainFocus() {
|
|
311
|
+
var hash = window.location.hash;
|
|
312
|
+
if (hash !== "" && $(hash)[0]) {
|
|
313
|
+
$(hash)[0].scrollIntoView();
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
setTimeout(function () {
|
|
317
|
+
$("#main").focus();
|
|
318
|
+
}, 10);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
$(document).ready(function () {
|
|
322
|
+
navResizer();
|
|
323
|
+
navExpander();
|
|
324
|
+
createSourceLinks();
|
|
325
|
+
createDefineLinks();
|
|
326
|
+
createFullTreeLinks();
|
|
327
|
+
searchFrameButtons();
|
|
328
|
+
linkSummaries();
|
|
329
|
+
summaryToggle();
|
|
330
|
+
constantSummaryToggle();
|
|
331
|
+
generateTOC();
|
|
332
|
+
mainFocus();
|
|
333
|
+
});
|
|
334
|
+
};
|
|
335
|
+
window.__app();
|
|
336
|
+
|
|
337
|
+
// Force sidebar links to do full page navigation instead of broken SPA
|
|
338
|
+
window.addEventListener("message", function (e) {
|
|
339
|
+
if (e.data.action === "navigate") {
|
|
340
|
+
// Calculate the correct absolute URL and do a real navigation
|
|
341
|
+
const nav = document.getElementById("nav");
|
|
342
|
+
const baseUrl = new URL(nav.src, window.location.href).href.replace(/[^/]*$/, '');
|
|
343
|
+
window.location.href = new URL(e.data.url, baseUrl).href;
|
|
344
|
+
}
|
|
345
|
+
}, false);
|
data/lib/app_query/base_query.rb
CHANGED
|
@@ -9,42 +9,46 @@ module AppQuery
|
|
|
9
9
|
# BaseQuery provides a structured way to work with SQL queries compared to
|
|
10
10
|
# using `AppQuery[:my_query]` directly.
|
|
11
11
|
#
|
|
12
|
+
# @see Paginatable Middleware for pagination support
|
|
13
|
+
# @see Mappable Middleware for mapping results to objects
|
|
14
|
+
#
|
|
12
15
|
# ## Benefits over AppQuery[:my_query]
|
|
13
16
|
#
|
|
14
17
|
# ### 1. Explicit parameter declaration
|
|
15
18
|
# Declare required binds and vars upfront with defaults:
|
|
16
19
|
#
|
|
17
|
-
#
|
|
18
|
-
#
|
|
19
|
-
#
|
|
20
|
-
#
|
|
21
|
-
#
|
|
20
|
+
# class ArticlesQuery < AppQuery::BaseQuery
|
|
21
|
+
# bind :author_id # required
|
|
22
|
+
# bind :status, default: nil # optional
|
|
23
|
+
# var :order_by, default: "created_at DESC"
|
|
24
|
+
# end
|
|
22
25
|
#
|
|
23
26
|
# ### 2. Unknown parameter validation
|
|
24
27
|
# Raises ArgumentError for typos or unknown parameters:
|
|
25
28
|
#
|
|
26
|
-
#
|
|
29
|
+
# ArticlesQuery.new(athor_id: 1)
|
|
30
|
+
# # => ArgumentError: Unknown param(s): athor_id
|
|
27
31
|
#
|
|
28
32
|
# ### 3. Self-documenting queries
|
|
29
33
|
# Query classes show exactly what parameters are available:
|
|
30
34
|
#
|
|
31
|
-
#
|
|
32
|
-
#
|
|
35
|
+
# ArticlesQuery.binds # => {author_id: {default: nil}, ...}
|
|
36
|
+
# ArticlesQuery.vars # => {order_by: {default: "created_at DESC"}}
|
|
33
37
|
#
|
|
34
38
|
# ### 4. Middleware support
|
|
35
39
|
# Include concerns to add functionality:
|
|
36
40
|
#
|
|
37
|
-
#
|
|
38
|
-
#
|
|
39
|
-
#
|
|
40
|
-
#
|
|
41
|
+
# class ApplicationQuery < AppQuery::BaseQuery
|
|
42
|
+
# include AppQuery::Paginatable
|
|
43
|
+
# include AppQuery::Mappable
|
|
44
|
+
# end
|
|
41
45
|
#
|
|
42
46
|
# ### 5. Casts
|
|
43
47
|
# Define casts for columns:
|
|
44
48
|
#
|
|
45
|
-
#
|
|
46
|
-
#
|
|
47
|
-
#
|
|
49
|
+
# class ApplicationQuery < AppQuery::BaseQuery
|
|
50
|
+
# cast metadata: :json
|
|
51
|
+
# end
|
|
48
52
|
#
|
|
49
53
|
# ## Parameter types
|
|
50
54
|
#
|
|
@@ -57,15 +61,13 @@ module AppQuery
|
|
|
57
61
|
# - `ArticlesQuery` -> `articles.sql.erb`
|
|
58
62
|
# - `Reports::MonthlyQuery` -> `reports/monthly.sql.erb`
|
|
59
63
|
#
|
|
60
|
-
#
|
|
61
|
-
#
|
|
62
|
-
# # app/queries/articles.sql.erb
|
|
64
|
+
# @example SQL template (app/queries/articles.sql.erb)
|
|
63
65
|
# SELECT * FROM articles
|
|
64
66
|
# WHERE author_id = :author_id
|
|
65
67
|
# <% if @status %>AND status = :status<% end %>
|
|
66
68
|
# ORDER BY <%= @order_by %>
|
|
67
69
|
#
|
|
68
|
-
#
|
|
70
|
+
# @example Query class (app/queries/articles_query.rb)
|
|
69
71
|
# class ArticlesQuery < AppQuery::BaseQuery
|
|
70
72
|
# bind :author_id
|
|
71
73
|
# bind :status, default: nil
|
|
@@ -73,7 +75,7 @@ module AppQuery
|
|
|
73
75
|
# cast published_at: :datetime
|
|
74
76
|
# end
|
|
75
77
|
#
|
|
76
|
-
#
|
|
78
|
+
# @example Usage
|
|
77
79
|
# ArticlesQuery.new(author_id: 1).entries
|
|
78
80
|
# ArticlesQuery.new(author_id: 1, status: "draft", order_by: "title").first
|
|
79
81
|
#
|
data/lib/app_query/mappable.rb
CHANGED
|
@@ -3,10 +3,19 @@
|
|
|
3
3
|
require "active_support/concern"
|
|
4
4
|
|
|
5
5
|
module AppQuery
|
|
6
|
-
#
|
|
6
|
+
# Middleware concern that maps query results to Ruby objects in {BaseQuery} subclasses.
|
|
7
7
|
#
|
|
8
|
-
#
|
|
9
|
-
#
|
|
8
|
+
# Include this module to automatically convert result hashes into typed objects
|
|
9
|
+
# like +Data+ classes or +Struct+s.
|
|
10
|
+
#
|
|
11
|
+
# By default, looks for an +Item+ constant in the query class.
|
|
12
|
+
# Use +map_to+ to specify a different class.
|
|
13
|
+
#
|
|
14
|
+
# @note This is a {BaseQuery} middleware. Include it in classes that inherit
|
|
15
|
+
# from {BaseQuery} to transform hash results into typed objects.
|
|
16
|
+
#
|
|
17
|
+
# @see BaseQuery Base class for query objects
|
|
18
|
+
# @see Paginatable Another middleware for pagination support
|
|
10
19
|
#
|
|
11
20
|
# @example With default Item class
|
|
12
21
|
# class ArticlesQuery < ApplicationQuery
|
|
@@ -31,6 +40,18 @@ module AppQuery
|
|
|
31
40
|
# @example Skip mapping with raw
|
|
32
41
|
# articles = ArticlesQuery.new.raw.entries
|
|
33
42
|
# articles.first # => {"title" => "Hello", "url" => "..."}
|
|
43
|
+
#
|
|
44
|
+
# @example Combining with Paginatable
|
|
45
|
+
# class ArticlesQuery < ApplicationQuery
|
|
46
|
+
# include AppQuery::Paginatable
|
|
47
|
+
# include AppQuery::Mappable
|
|
48
|
+
#
|
|
49
|
+
# class Item < Data.define(:title, :url)
|
|
50
|
+
# end
|
|
51
|
+
# end
|
|
52
|
+
#
|
|
53
|
+
# # Results are paginated AND mapped to Item objects
|
|
54
|
+
# ArticlesQuery.new.paginate(page: 1).entries.first.title
|
|
34
55
|
module Mappable
|
|
35
56
|
extend ActiveSupport::Concern
|
|
36
57
|
|
|
@@ -3,13 +3,20 @@
|
|
|
3
3
|
require "active_support/concern"
|
|
4
4
|
|
|
5
5
|
module AppQuery
|
|
6
|
-
#
|
|
6
|
+
# Middleware concern that adds pagination support to {BaseQuery} subclasses.
|
|
7
|
+
#
|
|
8
|
+
# Include this module in your query class to enable pagination with
|
|
9
|
+
# Kaminari-compatible result objects.
|
|
7
10
|
#
|
|
8
11
|
# Provides two modes:
|
|
9
12
|
# - **With count**: Full pagination with page numbers (uses COUNT query)
|
|
10
13
|
# - **Without count**: Simple prev/next for large datasets (uses limit+1 trick)
|
|
11
14
|
#
|
|
12
|
-
#
|
|
15
|
+
# @note This is a {BaseQuery} middleware. Include it in classes that inherit
|
|
16
|
+
# from {BaseQuery} and use the +paginate+ ERB helper in your SQL template.
|
|
17
|
+
#
|
|
18
|
+
# @see BaseQuery Base class for query objects
|
|
19
|
+
# @see Mappable Another middleware for mapping results to objects
|
|
13
20
|
#
|
|
14
21
|
# @example Basic usage
|
|
15
22
|
# class ApplicationQuery < AppQuery::BaseQuery
|
|
@@ -29,6 +36,12 @@ module AppQuery
|
|
|
29
36
|
# # Without count (large datasets)
|
|
30
37
|
# articles = ArticlesQuery.new.paginate(page: 1, without_count: true).entries
|
|
31
38
|
# articles.next_page # => 2 (or nil if last page)
|
|
39
|
+
#
|
|
40
|
+
# @example SQL template with pagination
|
|
41
|
+
# -- app/queries/articles.sql
|
|
42
|
+
# SELECT * FROM articles
|
|
43
|
+
# ORDER BY published_on DESC
|
|
44
|
+
# <%= paginate(page: page, per_page: per_page) %>
|
|
32
45
|
module Paginatable
|
|
33
46
|
extend ActiveSupport::Concern
|
|
34
47
|
|
data/lib/app_query/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: appquery
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.7.0.
|
|
4
|
+
version: 0.7.0.rc5
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Gert Goet
|
|
@@ -44,6 +44,7 @@ files:
|
|
|
44
44
|
- ".rspec"
|
|
45
45
|
- ".standard.yml"
|
|
46
46
|
- ".yard/templates/default/fulldoc/html/css/dark.css"
|
|
47
|
+
- ".yard/templates/default/fulldoc/html/js/app.js"
|
|
47
48
|
- ".yard/templates/default/fulldoc/html/setup.rb"
|
|
48
49
|
- ".yard/templates/default/layout/html/setup.rb"
|
|
49
50
|
- ".yardopts"
|