rep 0.1.1 → 0.9.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/.travis.yml +1 -1
- data/README.md +0 -12
- data/Rakefile +6 -8
- data/docs/docco.css +500 -0
- data/docs/index.html +408 -393
- data/docs/public/fonts/aller-bold.eot +0 -0
- data/docs/public/fonts/aller-bold.ttf +0 -0
- data/docs/public/fonts/aller-bold.woff +0 -0
- data/docs/public/fonts/aller-light.eot +0 -0
- data/docs/public/fonts/aller-light.ttf +0 -0
- data/docs/public/fonts/aller-light.woff +0 -0
- data/docs/public/fonts/novecento-bold.eot +0 -0
- data/docs/public/fonts/novecento-bold.ttf +0 -0
- data/docs/public/fonts/novecento-bold.woff +0 -0
- data/docs/public/stylesheets/normalize.css +375 -0
- data/docs/rep.html +408 -393
- data/lib/rep.rb +8 -14
- data/lib/rep/version.rb +1 -1
- data/rep.gemspec +3 -2
- metadata +20 -26
- data/docs/lib/rep.html +0 -484
- data/docs/lib/rep/version.html +0 -44
- data/docs/rep/version.html +0 -44
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1,375 @@
|
|
1
|
+
/*! normalize.css v2.0.1 | MIT License | git.io/normalize */
|
2
|
+
|
3
|
+
/* ==========================================================================
|
4
|
+
HTML5 display definitions
|
5
|
+
========================================================================== */
|
6
|
+
|
7
|
+
/*
|
8
|
+
* Corrects `block` display not defined in IE 8/9.
|
9
|
+
*/
|
10
|
+
|
11
|
+
article,
|
12
|
+
aside,
|
13
|
+
details,
|
14
|
+
figcaption,
|
15
|
+
figure,
|
16
|
+
footer,
|
17
|
+
header,
|
18
|
+
hgroup,
|
19
|
+
nav,
|
20
|
+
section,
|
21
|
+
summary {
|
22
|
+
display: block;
|
23
|
+
}
|
24
|
+
|
25
|
+
/*
|
26
|
+
* Corrects `inline-block` display not defined in IE 8/9.
|
27
|
+
*/
|
28
|
+
|
29
|
+
audio,
|
30
|
+
canvas,
|
31
|
+
video {
|
32
|
+
display: inline-block;
|
33
|
+
}
|
34
|
+
|
35
|
+
/*
|
36
|
+
* Prevents modern browsers from displaying `audio` without controls.
|
37
|
+
* Remove excess height in iOS 5 devices.
|
38
|
+
*/
|
39
|
+
|
40
|
+
audio:not([controls]) {
|
41
|
+
display: none;
|
42
|
+
height: 0;
|
43
|
+
}
|
44
|
+
|
45
|
+
/*
|
46
|
+
* Addresses styling for `hidden` attribute not present in IE 8/9.
|
47
|
+
*/
|
48
|
+
|
49
|
+
[hidden] {
|
50
|
+
display: none;
|
51
|
+
}
|
52
|
+
|
53
|
+
/* ==========================================================================
|
54
|
+
Base
|
55
|
+
========================================================================== */
|
56
|
+
|
57
|
+
/*
|
58
|
+
* 1. Sets default font family to sans-serif.
|
59
|
+
* 2. Prevents iOS text size adjust after orientation change, without disabling
|
60
|
+
* user zoom.
|
61
|
+
*/
|
62
|
+
|
63
|
+
html {
|
64
|
+
font-family: sans-serif; /* 1 */
|
65
|
+
-webkit-text-size-adjust: 100%; /* 2 */
|
66
|
+
-ms-text-size-adjust: 100%; /* 2 */
|
67
|
+
}
|
68
|
+
|
69
|
+
/*
|
70
|
+
* Removes default margin.
|
71
|
+
*/
|
72
|
+
|
73
|
+
body {
|
74
|
+
margin: 0;
|
75
|
+
}
|
76
|
+
|
77
|
+
/* ==========================================================================
|
78
|
+
Links
|
79
|
+
========================================================================== */
|
80
|
+
|
81
|
+
/*
|
82
|
+
* Addresses `outline` inconsistency between Chrome and other browsers.
|
83
|
+
*/
|
84
|
+
|
85
|
+
a:focus {
|
86
|
+
outline: thin dotted;
|
87
|
+
}
|
88
|
+
|
89
|
+
/*
|
90
|
+
* Improves readability when focused and also mouse hovered in all browsers.
|
91
|
+
*/
|
92
|
+
|
93
|
+
a:active,
|
94
|
+
a:hover {
|
95
|
+
outline: 0;
|
96
|
+
}
|
97
|
+
|
98
|
+
/* ==========================================================================
|
99
|
+
Typography
|
100
|
+
========================================================================== */
|
101
|
+
|
102
|
+
/*
|
103
|
+
* Addresses `h1` font sizes within `section` and `article` in Firefox 4+,
|
104
|
+
* Safari 5, and Chrome.
|
105
|
+
*/
|
106
|
+
|
107
|
+
h1 {
|
108
|
+
font-size: 2em;
|
109
|
+
}
|
110
|
+
|
111
|
+
/*
|
112
|
+
* Addresses styling not present in IE 8/9, Safari 5, and Chrome.
|
113
|
+
*/
|
114
|
+
|
115
|
+
abbr[title] {
|
116
|
+
border-bottom: 1px dotted;
|
117
|
+
}
|
118
|
+
|
119
|
+
/*
|
120
|
+
* Addresses style set to `bolder` in Firefox 4+, Safari 5, and Chrome.
|
121
|
+
*/
|
122
|
+
|
123
|
+
b,
|
124
|
+
strong {
|
125
|
+
font-weight: bold;
|
126
|
+
}
|
127
|
+
|
128
|
+
/*
|
129
|
+
* Addresses styling not present in Safari 5 and Chrome.
|
130
|
+
*/
|
131
|
+
|
132
|
+
dfn {
|
133
|
+
font-style: italic;
|
134
|
+
}
|
135
|
+
|
136
|
+
/*
|
137
|
+
* Addresses styling not present in IE 8/9.
|
138
|
+
*/
|
139
|
+
|
140
|
+
mark {
|
141
|
+
background: #ff0;
|
142
|
+
color: #000;
|
143
|
+
}
|
144
|
+
|
145
|
+
|
146
|
+
/*
|
147
|
+
* Corrects font family set oddly in Safari 5 and Chrome.
|
148
|
+
*/
|
149
|
+
|
150
|
+
code,
|
151
|
+
kbd,
|
152
|
+
pre,
|
153
|
+
samp {
|
154
|
+
font-family: monospace, serif;
|
155
|
+
font-size: 1em;
|
156
|
+
}
|
157
|
+
|
158
|
+
/*
|
159
|
+
* Improves readability of pre-formatted text in all browsers.
|
160
|
+
*/
|
161
|
+
|
162
|
+
pre {
|
163
|
+
white-space: pre;
|
164
|
+
white-space: pre-wrap;
|
165
|
+
word-wrap: break-word;
|
166
|
+
}
|
167
|
+
|
168
|
+
/*
|
169
|
+
* Sets consistent quote types.
|
170
|
+
*/
|
171
|
+
|
172
|
+
q {
|
173
|
+
quotes: "\201C" "\201D" "\2018" "\2019";
|
174
|
+
}
|
175
|
+
|
176
|
+
/*
|
177
|
+
* Addresses inconsistent and variable font size in all browsers.
|
178
|
+
*/
|
179
|
+
|
180
|
+
small {
|
181
|
+
font-size: 80%;
|
182
|
+
}
|
183
|
+
|
184
|
+
/*
|
185
|
+
* Prevents `sub` and `sup` affecting `line-height` in all browsers.
|
186
|
+
*/
|
187
|
+
|
188
|
+
sub,
|
189
|
+
sup {
|
190
|
+
font-size: 75%;
|
191
|
+
line-height: 0;
|
192
|
+
position: relative;
|
193
|
+
vertical-align: baseline;
|
194
|
+
}
|
195
|
+
|
196
|
+
sup {
|
197
|
+
top: -0.5em;
|
198
|
+
}
|
199
|
+
|
200
|
+
sub {
|
201
|
+
bottom: -0.25em;
|
202
|
+
}
|
203
|
+
|
204
|
+
/* ==========================================================================
|
205
|
+
Embedded content
|
206
|
+
========================================================================== */
|
207
|
+
|
208
|
+
/*
|
209
|
+
* Removes border when inside `a` element in IE 8/9.
|
210
|
+
*/
|
211
|
+
|
212
|
+
img {
|
213
|
+
border: 0;
|
214
|
+
}
|
215
|
+
|
216
|
+
/*
|
217
|
+
* Corrects overflow displayed oddly in IE 9.
|
218
|
+
*/
|
219
|
+
|
220
|
+
svg:not(:root) {
|
221
|
+
overflow: hidden;
|
222
|
+
}
|
223
|
+
|
224
|
+
/* ==========================================================================
|
225
|
+
Figures
|
226
|
+
========================================================================== */
|
227
|
+
|
228
|
+
/*
|
229
|
+
* Addresses margin not present in IE 8/9 and Safari 5.
|
230
|
+
*/
|
231
|
+
|
232
|
+
figure {
|
233
|
+
margin: 0;
|
234
|
+
}
|
235
|
+
|
236
|
+
/* ==========================================================================
|
237
|
+
Forms
|
238
|
+
========================================================================== */
|
239
|
+
|
240
|
+
/*
|
241
|
+
* Define consistent border, margin, and padding.
|
242
|
+
*/
|
243
|
+
|
244
|
+
fieldset {
|
245
|
+
border: 1px solid #c0c0c0;
|
246
|
+
margin: 0 2px;
|
247
|
+
padding: 0.35em 0.625em 0.75em;
|
248
|
+
}
|
249
|
+
|
250
|
+
/*
|
251
|
+
* 1. Corrects color not being inherited in IE 8/9.
|
252
|
+
* 2. Remove padding so people aren't caught out if they zero out fieldsets.
|
253
|
+
*/
|
254
|
+
|
255
|
+
legend {
|
256
|
+
border: 0; /* 1 */
|
257
|
+
padding: 0; /* 2 */
|
258
|
+
}
|
259
|
+
|
260
|
+
/*
|
261
|
+
* 1. Corrects font family not being inherited in all browsers.
|
262
|
+
* 2. Corrects font size not being inherited in all browsers.
|
263
|
+
* 3. Addresses margins set differently in Firefox 4+, Safari 5, and Chrome
|
264
|
+
*/
|
265
|
+
|
266
|
+
button,
|
267
|
+
input,
|
268
|
+
select,
|
269
|
+
textarea {
|
270
|
+
font-family: inherit; /* 1 */
|
271
|
+
font-size: 100%; /* 2 */
|
272
|
+
margin: 0; /* 3 */
|
273
|
+
}
|
274
|
+
|
275
|
+
/*
|
276
|
+
* Addresses Firefox 4+ setting `line-height` on `input` using `!important` in
|
277
|
+
* the UA stylesheet.
|
278
|
+
*/
|
279
|
+
|
280
|
+
button,
|
281
|
+
input {
|
282
|
+
line-height: normal;
|
283
|
+
}
|
284
|
+
|
285
|
+
/*
|
286
|
+
* 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
|
287
|
+
* and `video` controls.
|
288
|
+
* 2. Corrects inability to style clickable `input` types in iOS.
|
289
|
+
* 3. Improves usability and consistency of cursor style between image-type
|
290
|
+
* `input` and others.
|
291
|
+
*/
|
292
|
+
|
293
|
+
button,
|
294
|
+
html input[type="button"], /* 1 */
|
295
|
+
input[type="reset"],
|
296
|
+
input[type="submit"] {
|
297
|
+
-webkit-appearance: button; /* 2 */
|
298
|
+
cursor: pointer; /* 3 */
|
299
|
+
}
|
300
|
+
|
301
|
+
/*
|
302
|
+
* Re-set default cursor for disabled elements.
|
303
|
+
*/
|
304
|
+
|
305
|
+
button[disabled],
|
306
|
+
input[disabled] {
|
307
|
+
cursor: default;
|
308
|
+
}
|
309
|
+
|
310
|
+
/*
|
311
|
+
* 1. Addresses box sizing set to `content-box` in IE 8/9.
|
312
|
+
* 2. Removes excess padding in IE 8/9.
|
313
|
+
*/
|
314
|
+
|
315
|
+
input[type="checkbox"],
|
316
|
+
input[type="radio"] {
|
317
|
+
box-sizing: border-box; /* 1 */
|
318
|
+
padding: 0; /* 2 */
|
319
|
+
}
|
320
|
+
|
321
|
+
/*
|
322
|
+
* 1. Addresses `appearance` set to `searchfield` in Safari 5 and Chrome.
|
323
|
+
* 2. Addresses `box-sizing` set to `border-box` in Safari 5 and Chrome
|
324
|
+
* (include `-moz` to future-proof).
|
325
|
+
*/
|
326
|
+
|
327
|
+
input[type="search"] {
|
328
|
+
-webkit-appearance: textfield; /* 1 */
|
329
|
+
-moz-box-sizing: content-box;
|
330
|
+
-webkit-box-sizing: content-box; /* 2 */
|
331
|
+
box-sizing: content-box;
|
332
|
+
}
|
333
|
+
|
334
|
+
/*
|
335
|
+
* Removes inner padding and search cancel button in Safari 5 and Chrome
|
336
|
+
* on OS X.
|
337
|
+
*/
|
338
|
+
|
339
|
+
input[type="search"]::-webkit-search-cancel-button,
|
340
|
+
input[type="search"]::-webkit-search-decoration {
|
341
|
+
-webkit-appearance: none;
|
342
|
+
}
|
343
|
+
|
344
|
+
/*
|
345
|
+
* Removes inner padding and border in Firefox 4+.
|
346
|
+
*/
|
347
|
+
|
348
|
+
button::-moz-focus-inner,
|
349
|
+
input::-moz-focus-inner {
|
350
|
+
border: 0;
|
351
|
+
padding: 0;
|
352
|
+
}
|
353
|
+
|
354
|
+
/*
|
355
|
+
* 1. Removes default vertical scrollbar in IE 8/9.
|
356
|
+
* 2. Improves readability and alignment in all browsers.
|
357
|
+
*/
|
358
|
+
|
359
|
+
textarea {
|
360
|
+
overflow: auto; /* 1 */
|
361
|
+
vertical-align: top; /* 2 */
|
362
|
+
}
|
363
|
+
|
364
|
+
/* ==========================================================================
|
365
|
+
Tables
|
366
|
+
========================================================================== */
|
367
|
+
|
368
|
+
/*
|
369
|
+
* Remove most spacing between table cells.
|
370
|
+
*/
|
371
|
+
|
372
|
+
table {
|
373
|
+
border-collapse: collapse;
|
374
|
+
border-spacing: 0;
|
375
|
+
}
|
data/docs/rep.html
CHANGED
@@ -1,58 +1,41 @@
|
|
1
1
|
<!DOCTYPE html>
|
2
|
+
|
2
3
|
<html>
|
3
4
|
<head>
|
4
|
-
<meta http-equiv="content-type" content="text/html;charset=utf-8">
|
5
5
|
<title>rep.rb</title>
|
6
|
-
<
|
6
|
+
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
7
|
+
<meta name="viewport" content="width=device-width, target-densitydpi=160dpi, initial-scale=1.0; maximum-scale=1.0; user-scalable=0;">
|
8
|
+
<link rel="stylesheet" media="all" href="docco.css" />
|
7
9
|
</head>
|
8
10
|
<body>
|
9
|
-
<div id=
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
<td class=docs>
|
30
|
-
<div class="pilwrap">
|
31
|
-
<a class="pilcrow" href="#section-1">¶</a>
|
32
|
-
</div>
|
33
|
-
<p><strong>Rep</strong> is a small module to endow any class to make json quickly. It solves four problems:</p>
|
34
|
-
|
11
|
+
<div id="container">
|
12
|
+
<div id="background"></div>
|
13
|
+
|
14
|
+
<ul class="sections">
|
15
|
+
|
16
|
+
<li id="title">
|
17
|
+
<div class="annotation">
|
18
|
+
<h1>rep.rb</h1>
|
19
|
+
</div>
|
20
|
+
</li>
|
21
|
+
|
22
|
+
|
23
|
+
|
24
|
+
<li id="section-1">
|
25
|
+
<div class="annotation">
|
26
|
+
|
27
|
+
<div class="pilwrap ">
|
28
|
+
<a class="pilcrow" href="#section-1">¶</a>
|
29
|
+
</div>
|
30
|
+
<p><strong>Rep</strong> is a small module to endow any class to make json quickly. It solves four problems:</p>
|
35
31
|
<ol>
|
36
32
|
<li>Enumerating top level keys for a json structure</li>
|
37
33
|
<li>Providing a convention for the value of those keys</li>
|
38
|
-
<li>Defining <code>attr_accessor</code
|
34
|
+
<li>Defining <code>attr_accessor</code>'s that are prefilled from an options hash given to <code>#initialize</code></li>
|
39
35
|
<li>Sharing instances to help GC</li>
|
40
36
|
</ol>
|
41
|
-
|
42
|
-
|
43
37
|
<p>The code is available on <a href="http://github.com/myobie/rep">github</a>.</p>
|
44
|
-
|
45
|
-
<td class=code>
|
46
|
-
<div class='highlight'><pre></pre></div>
|
47
|
-
</td>
|
48
|
-
</tr>
|
49
|
-
<tr id='section-2'>
|
50
|
-
<td class=docs>
|
51
|
-
<div class="pilwrap">
|
52
|
-
<a class="pilcrow" href="#section-2">¶</a>
|
53
|
-
</div>
|
54
|
-
<p><code>Forwardable</code> is in the stdlib and allows ruby objects to delegate methods off to other objects. An example:</p>
|
55
|
-
|
38
|
+
<p><code>Forwardable</code> is in the stdlib and allows ruby objects to delegate methods off to other objects. An example:</p>
|
56
39
|
<pre><code>class A
|
57
40
|
extend Forwardable
|
58
41
|
delegate [:length, :first] => :@array
|
@@ -64,386 +47,423 @@ end
|
|
64
47
|
A.new([1,2,3]).length # => 3
|
65
48
|
A.new([1,2,3]).first # => 1
|
66
49
|
</code></pre>
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
<
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
50
|
+
</div>
|
51
|
+
|
52
|
+
<div class="content"><div class='highlight'><pre><span class="hljs-keyword">require</span> <span class="hljs-string">'forwardable'</span></pre></div></div>
|
53
|
+
|
54
|
+
</li>
|
55
|
+
|
56
|
+
|
57
|
+
<li id="section-2">
|
58
|
+
<div class="annotation">
|
59
|
+
|
60
|
+
<div class="pilwrap ">
|
61
|
+
<a class="pilcrow" href="#section-2">¶</a>
|
62
|
+
</div>
|
63
|
+
<p><code>JSON::generate</code> and <code>JSON::decode</code> are much safer to use than <code>Object#to_json</code>.</p>
|
64
|
+
|
65
|
+
</div>
|
66
|
+
|
67
|
+
<div class="content"><div class='highlight'><pre><span class="hljs-keyword">require</span> <span class="hljs-string">'json'</span>
|
68
|
+
|
69
|
+
<span class="hljs-keyword">require</span> <span class="hljs-string">'rep/version'</span>
|
70
|
+
<span class="hljs-class"><span class="hljs-keyword">module</span> <span class="hljs-title">Rep</span></span></pre></div></div>
|
71
|
+
|
72
|
+
</li>
|
73
|
+
|
74
|
+
|
75
|
+
<li id="section-3">
|
76
|
+
<div class="annotation">
|
77
|
+
|
78
|
+
<div class="pilwrap ">
|
79
|
+
<a class="pilcrow" href="#section-3">¶</a>
|
80
|
+
</div>
|
81
|
+
<p>All classes that <code>include Rep</code> are extended with <code>Forwardable</code>,
|
92
82
|
given some aliases, endowned with <code>HashieSupport</code> if Hashie is loaded,
|
93
|
-
and given a delegate method if it doesn
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
83
|
+
and given a delegate method if it doesn't already have one.</p>
|
84
|
+
|
85
|
+
</div>
|
86
|
+
|
87
|
+
<div class="content"><div class='highlight'><pre> <span class="hljs-function"><span class="hljs-keyword">def</span> </span><span class="hljs-keyword">self</span>.included(klass)
|
88
|
+
klass.extend <span class="hljs-constant">Forwardable</span>
|
89
|
+
klass.extend <span class="hljs-constant">ClassMethods</span>
|
90
|
+
klass.instance_eval {
|
91
|
+
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-inheritance"><</span><span class="hljs-inheritance">< <span class="hljs-parent">self</span></span></span>
|
92
|
+
<span class="hljs-keyword">unless</span> <span class="hljs-keyword">defined</span>?(forward)
|
93
|
+
<span class="hljs-keyword">alias</span> forward delegate
|
94
|
+
<span class="hljs-keyword">end</span>
|
95
|
+
|
96
|
+
<span class="hljs-keyword">unless</span> <span class="hljs-keyword">defined</span>?(fields)
|
97
|
+
<span class="hljs-keyword">alias</span> fields json_fields
|
98
|
+
<span class="hljs-keyword">end</span>
|
99
|
+
<span class="hljs-keyword">end</span>
|
100
|
+
|
101
|
+
<span class="hljs-keyword">if</span> <span class="hljs-keyword">defined</span>?(<span class="hljs-constant">Mashed</span>)
|
102
|
+
<span class="hljs-keyword">include</span> <span class="hljs-constant">MashedSupport</span>
|
103
|
+
<span class="hljs-keyword">end</span>
|
104
|
+
}
|
105
|
+
<span class="hljs-keyword">end</span></pre></div></div>
|
106
|
+
|
107
|
+
</li>
|
108
|
+
|
109
|
+
|
110
|
+
<li id="section-4">
|
111
|
+
<div class="annotation">
|
112
|
+
|
113
|
+
<div class="pilwrap ">
|
114
|
+
<a class="pilcrow" href="#section-4">¶</a>
|
115
|
+
</div>
|
116
|
+
<p>Since a goal is to be able to share instances, we need an easy way to reset a
|
123
117
|
shared instance back to factory defaults. If you memoize any methods that are
|
124
118
|
not declared as json fields, then overried this method and set any memoized
|
125
119
|
variables to nil, then super.</p>
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
120
|
+
|
121
|
+
</div>
|
122
|
+
|
123
|
+
<div class="content"><div class='highlight'><pre> <span class="hljs-function"><span class="hljs-keyword">def</span> </span>reset_for_json!
|
124
|
+
<span class="hljs-keyword">self</span>.<span class="hljs-keyword">class</span>.all_json_methods.each <span class="hljs-keyword">do</span> |method_name|
|
125
|
+
instance_variable_set(<span class="hljs-symbol">:<span class="hljs-string">"@<span class="hljs-subst">#{method_name}</span>"</span></span>, <span class="hljs-keyword">nil</span>)
|
126
|
+
<span class="hljs-keyword">end</span>
|
127
|
+
<span class="hljs-keyword">end</span></pre></div></div>
|
128
|
+
|
129
|
+
</li>
|
130
|
+
|
131
|
+
|
132
|
+
<li id="section-5">
|
133
|
+
<div class="annotation">
|
134
|
+
|
135
|
+
<div class="pilwrap ">
|
136
|
+
<a class="pilcrow" href="#section-5">¶</a>
|
137
|
+
</div>
|
138
|
+
<p>All the work of generating a hash from an instance is packaged up in one method. Since
|
141
139
|
fields can be aliases in the format <code>{ :json_key_name => :method_name }</code>, there
|
142
140
|
is some fancy logic to determine the <code>field_name</code> and <code>method_name</code> variables.</p>
|
143
|
-
|
144
141
|
<pre><code>{ :one => :foo }.to_a # => [[:one, :foo]]
|
145
|
-
</code></pre>
|
146
|
-
|
147
|
-
<p>Right now it will raise if either a field doesn’t have a method to provide it’s value or
|
142
|
+
</code></pre><p>Right now it will raise if either a field doesn't have a method to provide it's value or
|
148
143
|
if there are no json fields setup for the particular set (which defaults to <code>:default</code>).</p>
|
149
|
-
</td>
|
150
|
-
<td class=code>
|
151
|
-
<div class='highlight'><pre> <span class="k">def</span> <span class="nf">to_hash</span><span class="p">(</span><span class="nb">name</span> <span class="o">=</span> <span class="ss">:default</span><span class="p">)</span>
|
152
|
-
<span class="k">if</span> <span class="n">fields</span> <span class="o">=</span> <span class="nb">self</span><span class="o">.</span><span class="n">class</span><span class="o">.</span><span class="n">json_fields</span><span class="p">(</span><span class="nb">name</span><span class="p">)</span>
|
153
|
-
<span class="n">fields</span><span class="o">.</span><span class="n">reduce</span><span class="p">({})</span> <span class="k">do</span> <span class="o">|</span><span class="n">memo</span><span class="p">,</span> <span class="n">field</span><span class="o">|</span>
|
154
|
-
<span class="n">field_name</span><span class="p">,</span> <span class="n">method_name</span> <span class="o">=</span> <span class="n">field</span><span class="o">.</span><span class="n">is_a?</span><span class="p">(</span><span class="no">Hash</span><span class="p">)</span> <span class="p">?</span> <span class="n">field</span><span class="o">.</span><span class="n">to_a</span><span class="o">.</span><span class="n">first</span> <span class="p">:</span> <span class="o">[</span><span class="n">field</span><span class="p">,</span> <span class="n">field</span><span class="o">]</span>
|
155
|
-
<span class="k">begin</span>
|
156
|
-
<span class="n">memo</span><span class="o">[</span><span class="n">field_name</span><span class="o">]</span> <span class="o">=</span> <span class="nb">send</span><span class="p">(</span><span class="n">method_name</span><span class="p">)</span>
|
157
|
-
<span class="k">rescue</span> <span class="no">NoMethodError</span> <span class="o">=></span> <span class="n">e</span>
|
158
|
-
<span class="n">message</span> <span class="o">=</span> <span class="s2">"There is no method named '</span><span class="si">#{</span><span class="n">method_name</span><span class="si">}</span><span class="s2">' for the class '</span><span class="si">#{</span><span class="nb">self</span><span class="o">.</span><span class="n">class</span><span class="si">}</span><span class="s2">' for the '</span><span class="si">#{</span><span class="nb">name</span><span class="si">}</span><span class="s2">' list of fields : </span><span class="si">#{</span><span class="n">e</span><span class="o">.</span><span class="n">message</span><span class="si">}</span><span class="s2">"</span>
|
159
|
-
<span class="k">raise</span> <span class="no">NoMethodError</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="n">message</span><span class="p">,</span> <span class="n">method_name</span><span class="p">,</span> <span class="n">e</span><span class="o">.</span><span class="n">args</span><span class="p">)</span>
|
160
|
-
<span class="k">end</span>
|
161
|
-
<span class="n">memo</span>
|
162
|
-
<span class="k">end</span>
|
163
|
-
<span class="k">else</span>
|
164
|
-
<span class="k">raise</span> <span class="s2">"There are no json fields under the name: </span><span class="si">#{</span><span class="nb">name</span><span class="si">}</span><span class="s2">"</span>
|
165
|
-
<span class="k">end</span>
|
166
|
-
<span class="k">end</span>
|
167
|
-
|
168
|
-
<span class="k">def</span> <span class="nf">to_json</span>
|
169
|
-
<span class="no">JSON</span><span class="o">.</span><span class="n">generate</span><span class="p">(</span><span class="n">to_hash</span><span class="p">)</span>
|
170
|
-
<span class="k">end</span>
|
171
|
-
|
172
|
-
<span class="k">module</span> <span class="nn">ClassMethods</span></pre></div>
|
173
|
-
</td>
|
174
|
-
</tr>
|
175
|
-
<tr id='section-7'>
|
176
|
-
<td class=docs>
|
177
|
-
<div class="pilwrap">
|
178
|
-
<a class="pilcrow" href="#section-7">¶</a>
|
179
|
-
</div>
|
180
|
-
<p>Defines an attr_accessor with a default value. The default for default is nil. Example:</p>
|
181
144
|
|
145
|
+
</div>
|
146
|
+
|
147
|
+
<div class="content"><div class='highlight'><pre> <span class="hljs-function"><span class="hljs-keyword">def</span> </span>to_hash(name = <span class="hljs-symbol">:default</span>)
|
148
|
+
<span class="hljs-keyword">if</span> fields = <span class="hljs-keyword">self</span>.<span class="hljs-keyword">class</span>.json_fields(name)
|
149
|
+
fields.each_with_object({}) <span class="hljs-keyword">do</span> |field, memo|
|
150
|
+
field_name, method_name = field.is_a?(<span class="hljs-constant">Hash</span>) ? field.to_a.first <span class="hljs-symbol">:</span> [field, field]
|
151
|
+
<span class="hljs-keyword">if</span> <span class="hljs-keyword">self</span>.respond_to?(method_name)
|
152
|
+
memo[field_name] = send(method_name)
|
153
|
+
<span class="hljs-keyword">else</span>
|
154
|
+
message = <span class="hljs-string">"There is no method named '<span class="hljs-subst">#{method_name}</span>' for the class '<span class="hljs-subst">#{<span class="hljs-keyword">self</span>.<span class="hljs-keyword">class</span>}</span>' for the '<span class="hljs-subst">#{name}</span>' list of fields : <span class="hljs-subst">#{e.message}</span>"</span>
|
155
|
+
raise <span class="hljs-constant">NoMethodError</span>.new(message, method_name, e.args)
|
156
|
+
<span class="hljs-keyword">end</span>
|
157
|
+
<span class="hljs-keyword">end</span>
|
158
|
+
<span class="hljs-keyword">else</span>
|
159
|
+
raise <span class="hljs-string">"There are no json fields under the name: <span class="hljs-subst">#{name}</span>"</span>
|
160
|
+
<span class="hljs-keyword">end</span>
|
161
|
+
<span class="hljs-keyword">end</span>
|
162
|
+
|
163
|
+
<span class="hljs-function"><span class="hljs-keyword">def</span> </span>to_mash(name = <span class="hljs-symbol">:default</span>)
|
164
|
+
<span class="hljs-constant">Mashed::Mash</span>.new(to_hash(name))
|
165
|
+
<span class="hljs-keyword">end</span>
|
166
|
+
|
167
|
+
<span class="hljs-function"><span class="hljs-keyword">def</span> </span>to_json
|
168
|
+
<span class="hljs-constant">JSON</span>.generate(to_hash)
|
169
|
+
<span class="hljs-keyword">end</span>
|
170
|
+
|
171
|
+
<span class="hljs-class"><span class="hljs-keyword">module</span> <span class="hljs-title">ClassMethods</span></span></pre></div></div>
|
172
|
+
|
173
|
+
</li>
|
174
|
+
|
175
|
+
|
176
|
+
<li id="section-6">
|
177
|
+
<div class="annotation">
|
178
|
+
|
179
|
+
<div class="pilwrap ">
|
180
|
+
<a class="pilcrow" href="#section-6">¶</a>
|
181
|
+
</div>
|
182
|
+
<p>Defines an attr_accessor with a default value. The default for default is nil. Example:</p>
|
182
183
|
<pre><code>class A
|
183
|
-
register_accessor :name =>
|
184
|
+
register_accessor :name => "No Name"
|
184
185
|
end
|
185
186
|
|
186
|
-
A.new.name # =>
|
187
|
+
A.new.name # => "No Name"
|
187
188
|
</code></pre>
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
<span class="
|
193
|
-
<span class="
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
<span class="
|
198
|
-
<span class="
|
199
|
-
<span class="
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
<
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
189
|
+
</div>
|
190
|
+
|
191
|
+
<div class="content"><div class='highlight'><pre> <span class="hljs-function"><span class="hljs-keyword">def</span> </span>register_accessor(acc)
|
192
|
+
name, default = acc.is_a?(<span class="hljs-constant">Hash</span>) ? acc.to_a.first <span class="hljs-symbol">:</span> [acc, <span class="hljs-keyword">nil</span>]
|
193
|
+
<span class="hljs-keyword">attr_accessor</span> name
|
194
|
+
<span class="hljs-keyword">if</span> default
|
195
|
+
define_method name <span class="hljs-keyword">do</span>
|
196
|
+
var_name = <span class="hljs-symbol">:<span class="hljs-string">"@<span class="hljs-subst">#{name}</span>"</span></span>
|
197
|
+
instance_variable_get(var_name) || instance_variable_set(var_name, default)
|
198
|
+
<span class="hljs-keyword">end</span>
|
199
|
+
<span class="hljs-keyword">end</span>
|
200
|
+
<span class="hljs-keyword">end</span></pre></div></div>
|
201
|
+
|
202
|
+
</li>
|
203
|
+
|
204
|
+
|
205
|
+
<li id="section-7">
|
206
|
+
<div class="annotation">
|
207
|
+
|
208
|
+
<div class="pilwrap ">
|
209
|
+
<a class="pilcrow" href="#section-7">¶</a>
|
210
|
+
</div>
|
211
|
+
<p>Defines an <code>#initialize</code> method that accepts a Hash argument and copies some keys out into <code>attr_accessors</code>.
|
212
|
+
If your class already has an <code>#iniatialize</code> method then this will overwrite it (so don't use it). <code>#initialize_with</code>
|
209
213
|
does not have to be used to use any other parts of Rep.</p>
|
210
|
-
</td>
|
211
|
-
<td class=code>
|
212
|
-
<div class='highlight'><pre> <span class="k">def</span> <span class="nf">initialize_with</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">)</span>
|
213
|
-
<span class="vi">@initializiation_args</span> <span class="o">=</span> <span class="n">args</span></pre></div>
|
214
|
-
</td>
|
215
|
-
</tr>
|
216
|
-
<tr id='section-9'>
|
217
|
-
<td class=docs>
|
218
|
-
<div class="pilwrap">
|
219
|
-
<a class="pilcrow" href="#section-9">¶</a>
|
220
|
-
</div>
|
221
|
-
<p>Remember what args we normally initialize with so we can refer to them when building shared instances.</p>
|
222
|
-
</td>
|
223
|
-
<td class=code>
|
224
|
-
<div class='highlight'><pre> <span class="k">if</span> <span class="n">defined?</span><span class="p">(</span><span class="n">define_singleton_method</span><span class="p">)</span>
|
225
|
-
<span class="n">define_singleton_method</span> <span class="ss">:initializiation_args</span> <span class="k">do</span>
|
226
|
-
<span class="vi">@initializiation_args</span>
|
227
|
-
<span class="k">end</span>
|
228
|
-
<span class="k">else</span>
|
229
|
-
<span class="n">singleton</span> <span class="o">=</span> <span class="k">class</span> <span class="o"><<</span> <span class="nb">self</span><span class="p">;</span> <span class="nb">self</span> <span class="k">end</span>
|
230
|
-
<span class="n">singleton</span><span class="o">.</span><span class="n">send</span> <span class="ss">:define_method</span><span class="p">,</span> <span class="ss">:initializiation_args</span><span class="p">,</span> <span class="nb">lambda</span> <span class="p">{</span> <span class="vi">@initializiation_args</span> <span class="p">}</span>
|
231
|
-
<span class="k">end</span></pre></div>
|
232
|
-
</td>
|
233
|
-
</tr>
|
234
|
-
<tr id='section-10'>
|
235
|
-
<td class=docs>
|
236
|
-
<div class="pilwrap">
|
237
|
-
<a class="pilcrow" href="#section-10">¶</a>
|
238
|
-
</div>
|
239
|
-
<p>Create an <code>attr_accessor</code> for each one. Defaults can be provided using the Hash version { :arg => :default_value }</p>
|
240
|
-
</td>
|
241
|
-
<td class=code>
|
242
|
-
<div class='highlight'><pre> <span class="n">args</span><span class="o">.</span><span class="n">each</span> <span class="p">{</span> <span class="o">|</span><span class="n">a</span><span class="o">|</span> <span class="n">register_accessor</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="p">}</span>
|
243
|
-
|
244
|
-
<span class="n">define_method</span><span class="p">(</span><span class="ss">:initialize</span><span class="p">)</span> <span class="p">{</span> <span class="o">|*</span><span class="n">args</span><span class="o">|</span>
|
245
|
-
<span class="n">opts</span> <span class="o">=</span> <span class="n">args</span><span class="o">.</span><span class="n">first</span> <span class="o">||</span> <span class="p">{}</span>
|
246
|
-
<span class="n">parse_opts</span><span class="p">(</span><span class="n">opts</span><span class="p">)</span>
|
247
|
-
<span class="p">}</span></pre></div>
|
248
|
-
</td>
|
249
|
-
</tr>
|
250
|
-
<tr id='section-11'>
|
251
|
-
<td class=docs>
|
252
|
-
<div class="pilwrap">
|
253
|
-
<a class="pilcrow" href="#section-11">¶</a>
|
254
|
-
</div>
|
255
|
-
<p><code>#parse_opts</code> is responsable for getting the <code>attr_accessor</code> values prefilled. Since defaults can be specified, it
|
256
|
-
must negotiate Hashes and use the first key of the hash for the <code>attr_accessor</code>’s name.</p>
|
257
|
-
</td>
|
258
|
-
<td class=code>
|
259
|
-
<div class='highlight'><pre> <span class="n">define_method</span> <span class="ss">:parse_opts</span> <span class="k">do</span> <span class="o">|</span><span class="n">opts</span><span class="o">|</span>
|
260
|
-
<span class="vi">@rep_options</span> <span class="o">=</span> <span class="n">opts</span>
|
261
|
-
<span class="nb">self</span><span class="o">.</span><span class="n">class</span><span class="o">.</span><span class="n">initializiation_args</span><span class="o">.</span><span class="n">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">field</span><span class="o">|</span>
|
262
|
-
<span class="nb">name</span> <span class="o">=</span> <span class="n">field</span><span class="o">.</span><span class="n">is_a?</span><span class="p">(</span><span class="no">Hash</span><span class="p">)</span> <span class="p">?</span> <span class="n">field</span><span class="o">.</span><span class="n">to_a</span><span class="o">.</span><span class="n">first</span><span class="o">.</span><span class="n">first</span> <span class="p">:</span> <span class="n">field</span>
|
263
|
-
<span class="nb">instance_variable_set</span><span class="p">(</span><span class="ss">:"@</span><span class="si">#{</span><span class="nb">name</span><span class="si">}</span><span class="ss">"</span><span class="p">,</span> <span class="n">opts</span><span class="o">[</span><span class="nb">name</span><span class="o">]</span><span class="p">)</span>
|
264
|
-
<span class="k">end</span>
|
265
|
-
<span class="k">end</span>
|
266
|
-
<span class="k">end</span></pre></div>
|
267
|
-
</td>
|
268
|
-
</tr>
|
269
|
-
<tr id='section-12'>
|
270
|
-
<td class=docs>
|
271
|
-
<div class="pilwrap">
|
272
|
-
<a class="pilcrow" href="#section-12">¶</a>
|
273
|
-
</div>
|
274
|
-
<p><code>#json_fields</code> setups up some class instance variables to remember sets of top level keys for json structures. Example:</p>
|
275
214
|
|
215
|
+
</div>
|
216
|
+
|
217
|
+
<div class="content"><div class='highlight'><pre> <span class="hljs-function"><span class="hljs-keyword">def</span> </span>initialize_with(*args, &blk)
|
218
|
+
<span class="hljs-variable">@initializiation_args</span> = args</pre></div></div>
|
219
|
+
|
220
|
+
</li>
|
221
|
+
|
222
|
+
|
223
|
+
<li id="section-8">
|
224
|
+
<div class="annotation">
|
225
|
+
|
226
|
+
<div class="pilwrap ">
|
227
|
+
<a class="pilcrow" href="#section-8">¶</a>
|
228
|
+
</div>
|
229
|
+
<p>Remember what args we normally initialize with so we can refer to them when building shared instances.</p>
|
230
|
+
|
231
|
+
</div>
|
232
|
+
|
233
|
+
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> <span class="hljs-keyword">defined</span>?(define_singleton_method)
|
234
|
+
define_singleton_method <span class="hljs-symbol">:initializiation_args</span> <span class="hljs-keyword">do</span>
|
235
|
+
<span class="hljs-variable">@initializiation_args</span>
|
236
|
+
<span class="hljs-keyword">end</span>
|
237
|
+
<span class="hljs-keyword">else</span>
|
238
|
+
singleton = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-inheritance"><</span><span class="hljs-inheritance">< <span class="hljs-parent">self</span></span>;</span> <span class="hljs-keyword">self</span> <span class="hljs-keyword">end</span>
|
239
|
+
singleton.send <span class="hljs-symbol">:define_method</span>, <span class="hljs-symbol">:initializiation_args</span>, lambda { <span class="hljs-variable">@initializiation_args</span> }
|
240
|
+
<span class="hljs-keyword">end</span></pre></div></div>
|
241
|
+
|
242
|
+
</li>
|
243
|
+
|
244
|
+
|
245
|
+
<li id="section-9">
|
246
|
+
<div class="annotation">
|
247
|
+
|
248
|
+
<div class="pilwrap ">
|
249
|
+
<a class="pilcrow" href="#section-9">¶</a>
|
250
|
+
</div>
|
251
|
+
<p>Create an <code>attr_accessor</code> for each one. Defaults can be provided using the Hash version { :arg => :default_value }</p>
|
252
|
+
|
253
|
+
</div>
|
254
|
+
|
255
|
+
<div class="content"><div class='highlight'><pre> args.each { |a| register_accessor(a) }
|
256
|
+
|
257
|
+
define_method(<span class="hljs-symbol">:initialize</span>) { |opts={}|
|
258
|
+
parse_opts(opts)
|
259
|
+
}</pre></div></div>
|
260
|
+
|
261
|
+
</li>
|
262
|
+
|
263
|
+
|
264
|
+
<li id="section-10">
|
265
|
+
<div class="annotation">
|
266
|
+
|
267
|
+
<div class="pilwrap ">
|
268
|
+
<a class="pilcrow" href="#section-10">¶</a>
|
269
|
+
</div>
|
270
|
+
<p><code>#parse_opts</code> is responsable for getting the <code>attr_accessor</code> values prefilled. Since defaults can be specified, it
|
271
|
+
must negotiate Hashes and use the first key of the hash for the <code>attr_accessor</code>'s name.</p>
|
272
|
+
|
273
|
+
</div>
|
274
|
+
|
275
|
+
<div class="content"><div class='highlight'><pre> define_method <span class="hljs-symbol">:parse_opts</span> <span class="hljs-keyword">do</span> |opts|
|
276
|
+
<span class="hljs-variable">@rep_options</span> = opts
|
277
|
+
blk.call(opts) <span class="hljs-keyword">unless</span> blk.<span class="hljs-keyword">nil</span>?
|
278
|
+
<span class="hljs-keyword">self</span>.<span class="hljs-keyword">class</span>.initializiation_args.each <span class="hljs-keyword">do</span> |field|
|
279
|
+
name = field.is_a?(<span class="hljs-constant">Hash</span>) ? field.to_a.first.first <span class="hljs-symbol">:</span> field
|
280
|
+
instance_variable_set(<span class="hljs-symbol">:<span class="hljs-string">"@<span class="hljs-subst">#{name}</span>"</span></span>, opts[name])
|
281
|
+
<span class="hljs-keyword">end</span>
|
282
|
+
<span class="hljs-keyword">end</span>
|
283
|
+
<span class="hljs-keyword">end</span></pre></div></div>
|
284
|
+
|
285
|
+
</li>
|
286
|
+
|
287
|
+
|
288
|
+
<li id="section-11">
|
289
|
+
<div class="annotation">
|
290
|
+
|
291
|
+
<div class="pilwrap ">
|
292
|
+
<a class="pilcrow" href="#section-11">¶</a>
|
293
|
+
</div>
|
294
|
+
<p><code>#json_fields</code> setups up some class instance variables to remember sets of top level keys for json structures. Example:</p>
|
276
295
|
<pre><code>class A
|
277
296
|
json_fields [:one, :two, :three] => :default
|
278
297
|
end
|
279
298
|
|
280
299
|
A.json_fields(:default) # => [:one, :two, :three]
|
281
|
-
</code></pre>
|
282
|
-
|
283
|
-
<p>There is a general assumption that each top level key’s value is provided by a method of the same name on an instance
|
300
|
+
</code></pre><p>There is a general assumption that each top level key's value is provided by a method of the same name on an instance
|
284
301
|
of the class. If this is not true, a Hash syntax can be used to alias to a different method name. Example:</p>
|
285
|
-
|
286
302
|
<pre><code>class A
|
287
303
|
json_fields [{ :one => :the_real_one_method }, :two, { :three => :some_other_three }] => :default
|
288
304
|
end
|
289
|
-
</code></pre>
|
290
|
-
|
291
|
-
<p>Once can also set multiple sets of fields. Example:</p>
|
292
|
-
|
305
|
+
</code></pre><p>Once can also set multiple sets of fields. Example:</p>
|
293
306
|
<pre><code>class A
|
294
307
|
json_fields [:one, :two, :three] => :default
|
295
308
|
json_fields [:five, :two, :six] => :other
|
296
309
|
end
|
297
|
-
</code></pre>
|
298
|
-
|
299
|
-
<p>And all fields are returned by calling <code>#json_fields</code> with no args. Example:</p>
|
300
|
-
|
310
|
+
</code></pre><p>And all fields are returned by calling <code>#json_fields</code> with no args. Example:</p>
|
301
311
|
<pre><code>A.json_fields # => { :default => [:one, :two, :three], :other => [:five, :two, :six] }
|
302
312
|
</code></pre>
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
<span class="
|
307
|
-
|
308
|
-
<span class="
|
309
|
-
<span class="
|
310
|
-
<span class="
|
311
|
-
<span class="
|
312
|
-
<span class="
|
313
|
-
<span class="
|
314
|
-
<span class="
|
315
|
-
<span class="
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
<
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
313
|
+
</div>
|
314
|
+
|
315
|
+
<div class="content"><div class='highlight'><pre> <span class="hljs-function"><span class="hljs-keyword">def</span> </span>json_fields(arg = <span class="hljs-keyword">nil</span>)
|
316
|
+
<span class="hljs-keyword">if</span> arg.is_a?(<span class="hljs-constant">Hash</span>)
|
317
|
+
fields, name = arg.to_a.first
|
318
|
+
<span class="hljs-variable">@json_fields</span> ||= {}
|
319
|
+
<span class="hljs-variable">@json_fields</span>[name] = [fields].flatten
|
320
|
+
<span class="hljs-keyword">elsif</span> arg.is_a?(<span class="hljs-constant">Symbol</span>)
|
321
|
+
<span class="hljs-variable">@json_fields</span> ||= {}
|
322
|
+
<span class="hljs-variable">@json_fields</span>[arg]
|
323
|
+
<span class="hljs-keyword">elsif</span> arg === <span class="hljs-keyword">nil</span>
|
324
|
+
<span class="hljs-variable">@json_fields</span> || {}
|
325
|
+
<span class="hljs-keyword">else</span></pre></div></div>
|
326
|
+
|
327
|
+
</li>
|
328
|
+
|
329
|
+
|
330
|
+
<li id="section-12">
|
331
|
+
<div class="annotation">
|
332
|
+
|
333
|
+
<div class="pilwrap ">
|
334
|
+
<a class="pilcrow" href="#section-12">¶</a>
|
335
|
+
</div>
|
336
|
+
<p>TODO: make an exception class</p>
|
337
|
+
|
338
|
+
</div>
|
339
|
+
|
340
|
+
<div class="content"><div class='highlight'><pre> raise <span class="hljs-string">"You can only use a Hash to set fields, a Symbol to retrieve them, or no argument to retrieve all fields for all names"</span>
|
341
|
+
<span class="hljs-keyword">end</span>
|
342
|
+
<span class="hljs-keyword">end</span></pre></div></div>
|
343
|
+
|
344
|
+
</li>
|
345
|
+
|
346
|
+
|
347
|
+
<li id="section-13">
|
348
|
+
<div class="annotation">
|
349
|
+
|
350
|
+
<div class="pilwrap ">
|
351
|
+
<a class="pilcrow" href="#section-13">¶</a>
|
352
|
+
</div>
|
353
|
+
<p><code>#flat_json_fields</code> is just a utility method to DRY up the next two methods, because their code is almost exactly the same,
|
337
354
|
it is not intended for use directly and might be confusing.</p>
|
338
|
-
</td>
|
339
|
-
<td class=code>
|
340
|
-
<div class='highlight'><pre> <span class="k">def</span> <span class="nf">flat_json_fields</span><span class="p">(</span><span class="n">side</span> <span class="o">=</span> <span class="ss">:right</span><span class="p">)</span>
|
341
|
-
<span class="n">side_number</span> <span class="o">=</span> <span class="n">side</span> <span class="o">==</span> <span class="ss">:right</span> <span class="p">?</span> <span class="mi">1</span> <span class="p">:</span> <span class="mi">0</span>
|
342
|
-
|
343
|
-
<span class="n">json_fields</span><span class="o">.</span><span class="n">reduce</span><span class="p">(</span><span class="o">[]</span><span class="p">)</span> <span class="k">do</span> <span class="o">|</span><span class="n">memo</span><span class="p">,</span> <span class="p">(</span><span class="nb">name</span><span class="p">,</span> <span class="n">fields</span><span class="p">)</span><span class="o">|</span>
|
344
|
-
<span class="n">memo</span> <span class="o">+</span> <span class="n">fields</span><span class="o">.</span><span class="n">map</span> <span class="k">do</span> <span class="o">|</span><span class="n">field</span><span class="o">|</span>
|
345
|
-
<span class="k">if</span> <span class="n">field</span><span class="o">.</span><span class="n">is_a?</span><span class="p">(</span><span class="no">Hash</span><span class="p">)</span>
|
346
|
-
<span class="n">field</span><span class="o">.</span><span class="n">to_a</span><span class="o">.</span><span class="n">first</span><span class="o">[</span><span class="n">side_number</span><span class="o">]</span> <span class="c1"># [name, method_name]</span>
|
347
|
-
<span class="k">else</span>
|
348
|
-
<span class="n">field</span>
|
349
|
-
<span class="k">end</span>
|
350
|
-
<span class="k">end</span>
|
351
|
-
<span class="k">end</span><span class="o">.</span><span class="n">uniq</span>
|
352
|
-
<span class="k">end</span></pre></div>
|
353
|
-
</td>
|
354
|
-
</tr>
|
355
|
-
<tr id='section-15'>
|
356
|
-
<td class=docs>
|
357
|
-
<div class="pilwrap">
|
358
|
-
<a class="pilcrow" href="#section-15">¶</a>
|
359
|
-
</div>
|
360
|
-
<p>We need a way to get a flat, uniq'ed list of all the fields accross all field sets. This is that.</p>
|
361
|
-
</td>
|
362
|
-
<td class=code>
|
363
|
-
<div class='highlight'><pre> <span class="k">def</span> <span class="nf">all_json_fields</span>
|
364
|
-
<span class="n">flat_json_fields</span><span class="p">(</span><span class="ss">:left</span><span class="p">)</span>
|
365
|
-
<span class="k">end</span></pre></div>
|
366
|
-
</td>
|
367
|
-
</tr>
|
368
|
-
<tr id='section-16'>
|
369
|
-
<td class=docs>
|
370
|
-
<div class="pilwrap">
|
371
|
-
<a class="pilcrow" href="#section-16">¶</a>
|
372
|
-
</div>
|
373
|
-
<p>We need a wya to get a flat, uniq'ed list of all the method names accross all field sets. This is that.</p>
|
374
|
-
</td>
|
375
|
-
<td class=code>
|
376
|
-
<div class='highlight'><pre> <span class="k">def</span> <span class="nf">all_json_methods</span>
|
377
|
-
<span class="n">flat_json_fields</span><span class="p">(</span><span class="ss">:right</span><span class="p">)</span>
|
378
|
-
<span class="k">end</span></pre></div>
|
379
|
-
</td>
|
380
|
-
</tr>
|
381
|
-
<tr id='section-17'>
|
382
|
-
<td class=docs>
|
383
|
-
<div class="pilwrap">
|
384
|
-
<a class="pilcrow" href="#section-17">¶</a>
|
385
|
-
</div>
|
386
|
-
<p>An easy way to save on GC is to use the same instance to turn an array of objects into hashes instead
|
387
|
-
of instantiating a new object for every object in the array. Here is an example of it’s usage:</p>
|
388
355
|
|
356
|
+
</div>
|
357
|
+
|
358
|
+
<div class="content"><div class='highlight'><pre> <span class="hljs-function"><span class="hljs-keyword">def</span> </span>flat_json_fields(side = <span class="hljs-symbol">:right</span>)
|
359
|
+
side_number = side == <span class="hljs-symbol">:right</span> ? <span class="hljs-number">1</span> <span class="hljs-symbol">:</span> <span class="hljs-number">0</span>
|
360
|
+
|
361
|
+
json_fields.reduce([]) <span class="hljs-keyword">do</span> |memo, (name, fields)|
|
362
|
+
memo + fields.map <span class="hljs-keyword">do</span> |field|
|
363
|
+
<span class="hljs-keyword">if</span> field.is_a?(<span class="hljs-constant">Hash</span>)
|
364
|
+
field.to_a.first[side_number] <span class="hljs-comment"># [name, method_name]</span>
|
365
|
+
<span class="hljs-keyword">else</span>
|
366
|
+
field
|
367
|
+
<span class="hljs-keyword">end</span>
|
368
|
+
<span class="hljs-keyword">end</span>
|
369
|
+
<span class="hljs-keyword">end</span>.uniq
|
370
|
+
<span class="hljs-keyword">end</span></pre></div></div>
|
371
|
+
|
372
|
+
</li>
|
373
|
+
|
374
|
+
|
375
|
+
<li id="section-14">
|
376
|
+
<div class="annotation">
|
377
|
+
|
378
|
+
<div class="pilwrap ">
|
379
|
+
<a class="pilcrow" href="#section-14">¶</a>
|
380
|
+
</div>
|
381
|
+
<p>We need a way to get a flat, uniq'ed list of all the fields accross all field sets. This is that.</p>
|
382
|
+
|
383
|
+
</div>
|
384
|
+
|
385
|
+
<div class="content"><div class='highlight'><pre> <span class="hljs-function"><span class="hljs-keyword">def</span> </span>all_json_fields
|
386
|
+
flat_json_fields(<span class="hljs-symbol">:left</span>)
|
387
|
+
<span class="hljs-keyword">end</span></pre></div></div>
|
388
|
+
|
389
|
+
</li>
|
390
|
+
|
391
|
+
|
392
|
+
<li id="section-15">
|
393
|
+
<div class="annotation">
|
394
|
+
|
395
|
+
<div class="pilwrap ">
|
396
|
+
<a class="pilcrow" href="#section-15">¶</a>
|
397
|
+
</div>
|
398
|
+
<p>We need a wya to get a flat, uniq'ed list of all the method names accross all field sets. This is that.</p>
|
399
|
+
|
400
|
+
</div>
|
401
|
+
|
402
|
+
<div class="content"><div class='highlight'><pre> <span class="hljs-function"><span class="hljs-keyword">def</span> </span>all_json_methods
|
403
|
+
flat_json_fields(<span class="hljs-symbol">:right</span>)
|
404
|
+
<span class="hljs-keyword">end</span></pre></div></div>
|
405
|
+
|
406
|
+
</li>
|
407
|
+
|
408
|
+
|
409
|
+
<li id="section-16">
|
410
|
+
<div class="annotation">
|
411
|
+
|
412
|
+
<div class="pilwrap ">
|
413
|
+
<a class="pilcrow" href="#section-16">¶</a>
|
414
|
+
</div>
|
415
|
+
<p>An easy way to save on GC is to use the same instance to turn an array of objects into hashes instead
|
416
|
+
of instantiating a new object for every object in the array. Here is an example of it's usage:</p>
|
389
417
|
<pre><code>class BookRep
|
390
418
|
initialize_with :book_model
|
391
419
|
fields :title => :default
|
392
420
|
forward :title => :book_model
|
393
421
|
end
|
394
422
|
|
395
|
-
BookRep.shared(:book_model => Book.first).to_hash # => { :title =>
|
396
|
-
BookRep.shared(:book_model => Book.last).to_hash # => { :title =>
|
397
|
-
</code></pre>
|
398
|
-
|
399
|
-
<p>This should terrify you. If it doesn’t, then this example will:</p>
|
400
|
-
|
423
|
+
BookRep.shared(:book_model => Book.first).to_hash # => { :title => "Moby Dick" }
|
424
|
+
BookRep.shared(:book_model => Book.last).to_hash # => { :title => "Lost Horizon" }
|
425
|
+
</code></pre><p>This should terrify you. If it doesn't, then this example will:</p>
|
401
426
|
<pre><code>book1 = BookRep.shared(:book_model => Book.first)
|
402
427
|
book2 = BookRep.shared(:book_model => Book.last)
|
403
428
|
|
404
429
|
boo1.object_id === book2.object_id # => true
|
405
|
-
</code></pre>
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
<
|
412
|
-
|
413
|
-
<span class="
|
414
|
-
<span class="
|
415
|
-
<span class="
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
430
|
+
</code></pre><p><strong>It really is a shared object.</strong></p>
|
431
|
+
<p>You really shouldn't use this method directly for anything.</p>
|
432
|
+
|
433
|
+
</div>
|
434
|
+
|
435
|
+
<div class="content"><div class='highlight'><pre> <span class="hljs-function"><span class="hljs-keyword">def</span> </span>shared(opts = {})
|
436
|
+
<span class="hljs-variable">@pointer</span> = (<span class="hljs-constant">Thread</span>.current[<span class="hljs-symbol">:rep_shared_instances</span>] ||= {})
|
437
|
+
<span class="hljs-variable">@pointer</span>[object_id] ||= new
|
438
|
+
<span class="hljs-variable">@pointer</span>[object_id].reset_for_json!
|
439
|
+
<span class="hljs-variable">@pointer</span>[object_id].parse_opts(opts)
|
440
|
+
<span class="hljs-variable">@pointer</span>[object_id]
|
441
|
+
<span class="hljs-keyword">end</span></pre></div></div>
|
442
|
+
|
443
|
+
</li>
|
444
|
+
|
445
|
+
|
446
|
+
<li id="section-17">
|
447
|
+
<div class="annotation">
|
448
|
+
|
449
|
+
<div class="pilwrap ">
|
450
|
+
<a class="pilcrow" href="#section-17">¶</a>
|
451
|
+
</div>
|
452
|
+
<p>The fanciest thing in this entire library is this <code>#to_proc</code> method. Here is an example of it's usage:</p>
|
428
453
|
<pre><code>class BookRep
|
429
454
|
initialize_with :book_model
|
430
455
|
fields :title => :default
|
431
456
|
forward :title => :book_model
|
432
457
|
end
|
433
458
|
|
434
|
-
Book.all.map(&BookRep) # => [{ :title =>
|
435
|
-
</code></pre>
|
436
|
-
|
437
|
-
<p>And now I will explain how it works. Any object can have a to_proc method and when you call <code>#map</code> on an
|
438
|
-
array and hand it a proc it will in turn hand each object as an argument to that proc. What I’ve decided
|
459
|
+
Book.all.map(&BookRep) # => [{ :title => "Moby Dick" }, { :title => "Lost Horizon " }]
|
460
|
+
</code></pre><p>And now I will explain how it works. Any object can have a to_proc method and when you call <code>#map</code> on an
|
461
|
+
array and hand it a proc it will in turn hand each object as an argument to that proc. What I've decided
|
439
462
|
to do with this object is use it the options for a shared instance to make a hash.</p>
|
440
|
-
|
441
463
|
<p>Since I know the different initialization argumants from a call to <code>initialize_with</code>, I can infer by order
|
442
464
|
which object is which option. Then I can create a Hash to give to <code>parse_opts</code> through the <code>shared</code> method.
|
443
465
|
I hope that makes sense.</p>
|
444
|
-
|
445
466
|
<p>It allows for extremely clean Rails controllers like this:</p>
|
446
|
-
|
447
467
|
<pre><code>class PhotosController < ApplicationController
|
448
468
|
respond_to :json, :html
|
449
469
|
|
@@ -458,27 +478,22 @@ I hope that makes sense.</p>
|
|
458
478
|
end
|
459
479
|
end
|
460
480
|
</code></pre>
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
<span class="k">end</span>
|
479
|
-
<span class="k">end</span></pre></div>
|
480
|
-
</td>
|
481
|
-
</tr>
|
482
|
-
</table>
|
483
|
-
</div>
|
481
|
+
</div>
|
482
|
+
|
483
|
+
<div class="content"><div class='highlight'><pre> <span class="hljs-function"><span class="hljs-keyword">def</span> </span>to_proc
|
484
|
+
proc { |obj|
|
485
|
+
arr = [obj].flatten
|
486
|
+
init_args = <span class="hljs-variable">@initializiation_args</span>[<span class="hljs-number">0</span>..(arr.length-<span class="hljs-number">1</span>)]
|
487
|
+
opts = <span class="hljs-constant">Hash</span>[init_args.zip(arr)]
|
488
|
+
shared(opts).to_hash
|
489
|
+
}
|
490
|
+
<span class="hljs-keyword">end</span>
|
491
|
+
<span class="hljs-keyword">end</span>
|
492
|
+
<span class="hljs-keyword">end</span></pre></div></div>
|
493
|
+
|
494
|
+
</li>
|
495
|
+
|
496
|
+
</ul>
|
497
|
+
</div>
|
484
498
|
</body>
|
499
|
+
</html>
|