spyro 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (107) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.rdoc +3 -0
  4. data/Rakefile +37 -0
  5. data/app/assets/OLDjavascripts/application.js +25 -0
  6. data/app/assets/OLDjavascripts/components.es6 +10 -0
  7. data/app/assets/OLDjavascripts/components/base/base.es6 +197 -0
  8. data/app/assets/OLDjavascripts/components/base/collection.es6 +199 -0
  9. data/app/assets/OLDjavascripts/components/base/element.es6 +134 -0
  10. data/app/assets/OLDjavascripts/components/base/field.es6 +26 -0
  11. data/app/assets/OLDjavascripts/components/base/inputs/text.es6 +21 -0
  12. data/app/assets/OLDjavascripts/components/base/pagination.es6 +23 -0
  13. data/app/assets/OLDjavascripts/vendor/lodash.js +121 -0
  14. data/app/assets/OLDjavascripts/vendor/moment-twitter.js +86 -0
  15. data/app/assets/OLDjavascripts/vendor/moment.js +80 -0
  16. data/app/assets/OLDjavascripts/vendor/pluralize.js +433 -0
  17. data/app/views/base/_associations.html.haml +11 -0
  18. data/app/views/base/_custom.html.haml +0 -0
  19. data/app/views/base/_details.html.haml +3 -0
  20. data/app/views/base/_edit_header.html.haml +3 -0
  21. data/app/views/base/_fields.html.haml +11 -0
  22. data/app/views/base/_form.html.haml +6 -0
  23. data/app/views/base/_index_header.html.haml +4 -0
  24. data/app/views/base/_new_header.html.haml +3 -0
  25. data/app/views/base/_other_form_fields.html.haml +0 -0
  26. data/app/views/base/_show_header.html.haml +9 -0
  27. data/app/views/base/_upload_fields.html.haml +5 -0
  28. data/app/views/base/copy.html.haml +10 -0
  29. data/app/views/base/edit.html.haml +4 -0
  30. data/app/views/base/index.csv.haml +8 -0
  31. data/app/views/base/index.html.haml +7 -0
  32. data/app/views/base/index.js.haml +2 -0
  33. data/app/views/base/index.xls.ruby +12 -0
  34. data/app/views/base/mailer.html.haml +46 -0
  35. data/app/views/base/new.html.haml +4 -0
  36. data/app/views/base/notify.html.haml +11 -0
  37. data/app/views/base/show.html.haml +8 -0
  38. data/app/views/base/stats.html.haml +36 -0
  39. data/app/views/base/trombi.html.haml +1 -0
  40. data/app/views/base/upload.html.haml +24 -0
  41. data/config/initializers/assets.rb +1 -0
  42. data/config/routes.rb +2 -0
  43. data/lib/spyro.rb +24 -0
  44. data/lib/spyro/active_record_add_on.rb +38 -0
  45. data/lib/spyro/application_controller_add_on.rb +24 -0
  46. data/lib/spyro/collections/outputs/admin_table.rb +28 -0
  47. data/lib/spyro/collections/outputs/bar_graph_table.rb +46 -0
  48. data/lib/spyro/collections/outputs/base.rb +23 -0
  49. data/lib/spyro/collections/outputs/csv.rb +34 -0
  50. data/lib/spyro/collections/outputs/fields.rb +118 -0
  51. data/lib/spyro/collections/outputs/flatui_table.rb +40 -0
  52. data/lib/spyro/collections/outputs/inplace_table.rb +29 -0
  53. data/lib/spyro/collections/outputs/map.rb +22 -0
  54. data/lib/spyro/collections/outputs/table.rb +126 -0
  55. data/lib/spyro/collections/outputs/xlsx.rb +39 -0
  56. data/lib/spyro/collections/parsers/active_ldap_relation.rb +22 -0
  57. data/lib/spyro/collections/parsers/active_record_relation.rb +138 -0
  58. data/lib/spyro/collections/parsers/array.rb +38 -0
  59. data/lib/spyro/collections/parsers/base.rb +60 -0
  60. data/lib/spyro/collections/parsers/kaminari_array.rb +38 -0
  61. data/lib/spyro/collections/parsers/model.rb +31 -0
  62. data/lib/spyro/controllers/strong_parameted.rb +33 -0
  63. data/lib/spyro/engine.rb +6 -0
  64. data/lib/spyro/filters_controller_add_on.rb +161 -0
  65. data/lib/spyro/helpers/action_view_extension.rb +726 -0
  66. data/lib/spyro/namespace_template_inheritance.rb +30 -0
  67. data/lib/spyro/usefull_attributes.rb +14 -0
  68. data/lib/spyro/version.rb +3 -0
  69. data/lib/tasks/spyro_tasks.rake +4 -0
  70. data/test/dummy/README.rdoc +28 -0
  71. data/test/dummy/Rakefile +6 -0
  72. data/test/dummy/app/assets/javascripts/application.js +13 -0
  73. data/test/dummy/app/assets/stylesheets/application.css +15 -0
  74. data/test/dummy/app/controllers/application_controller.rb +5 -0
  75. data/test/dummy/app/helpers/application_helper.rb +2 -0
  76. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  77. data/test/dummy/bin/bundle +3 -0
  78. data/test/dummy/bin/rails +4 -0
  79. data/test/dummy/bin/rake +4 -0
  80. data/test/dummy/bin/setup +29 -0
  81. data/test/dummy/config.ru +4 -0
  82. data/test/dummy/config/application.rb +26 -0
  83. data/test/dummy/config/boot.rb +5 -0
  84. data/test/dummy/config/database.yml +25 -0
  85. data/test/dummy/config/environment.rb +5 -0
  86. data/test/dummy/config/environments/development.rb +41 -0
  87. data/test/dummy/config/environments/production.rb +79 -0
  88. data/test/dummy/config/environments/test.rb +42 -0
  89. data/test/dummy/config/initializers/assets.rb +11 -0
  90. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  91. data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
  92. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  93. data/test/dummy/config/initializers/inflections.rb +16 -0
  94. data/test/dummy/config/initializers/mime_types.rb +4 -0
  95. data/test/dummy/config/initializers/session_store.rb +3 -0
  96. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  97. data/test/dummy/config/locales/en.yml +23 -0
  98. data/test/dummy/config/routes.rb +4 -0
  99. data/test/dummy/config/secrets.yml +22 -0
  100. data/test/dummy/public/404.html +67 -0
  101. data/test/dummy/public/422.html +67 -0
  102. data/test/dummy/public/500.html +66 -0
  103. data/test/dummy/public/favicon.ico +0 -0
  104. data/test/integration/navigation_test.rb +8 -0
  105. data/test/spyro_test.rb +7 -0
  106. data/test/test_helper.rb +21 -0
  107. metadata +256 -0
@@ -0,0 +1,433 @@
1
+ /* global define */
2
+
3
+ (function (root, pluralize) {
4
+ /* istanbul ignore else */
5
+ if (typeof require === 'function' && typeof exports === 'object' && typeof module === 'object') {
6
+ // Node.
7
+ module.exports = pluralize();
8
+ } else if (typeof define === 'function' && define.amd) {
9
+ // AMD, registers as an anonymous module.
10
+ define(function () {
11
+ return pluralize();
12
+ });
13
+ } else {
14
+ // Browser global.
15
+ root.pluralize = pluralize();
16
+ }
17
+ })(this, function () {
18
+ // Rule storage - pluralize and singularize need to be run sequentially,
19
+ // while other rules can be optimized using an object for instant lookups.
20
+ var pluralRules = [];
21
+ var singularRules = [];
22
+ var uncountables = {};
23
+ var irregularPlurals = {};
24
+ var irregularSingles = {};
25
+
26
+ /**
27
+ * Title case a string.
28
+ *
29
+ * @param {string} str
30
+ * @return {string}
31
+ */
32
+ function toTitleCase (str) {
33
+ return str.charAt(0).toUpperCase() + str.substr(1).toLowerCase();
34
+ }
35
+
36
+ /**
37
+ * Sanitize a pluralization rule to a usable regular expression.
38
+ *
39
+ * @param {(RegExp|string)} rule
40
+ * @return {RegExp}
41
+ */
42
+ function sanitizeRule (rule) {
43
+ if (typeof rule === 'string') {
44
+ return new RegExp('^' + rule + '$', 'i');
45
+ }
46
+
47
+ return rule;
48
+ }
49
+
50
+ /**
51
+ * Pass in a word token to produce a function that can replicate the case on
52
+ * another word.
53
+ *
54
+ * @param {string} word
55
+ * @param {string} token
56
+ * @return {Function}
57
+ */
58
+ function restoreCase (word, token) {
59
+ // Upper cased words. E.g. "HELLO".
60
+ if (word === word.toUpperCase()) {
61
+ return token.toUpperCase();
62
+ }
63
+
64
+ // Title cased words. E.g. "Title".
65
+ if (word[0] === word[0].toUpperCase()) {
66
+ return toTitleCase(token);
67
+ }
68
+
69
+ // Lower cased words. E.g. "test".
70
+ return token.toLowerCase();
71
+ }
72
+
73
+ /**
74
+ * Interpolate a regexp string.
75
+ *
76
+ * @param {string} str
77
+ * @param {Array} args
78
+ * @return {string}
79
+ */
80
+ function interpolate (str, args) {
81
+ return str.replace(/\$(\d{1,2})/g, function (match, index) {
82
+ return args[index] || '';
83
+ });
84
+ }
85
+
86
+ /**
87
+ * Sanitize a word by passing in the word and sanitization rules.
88
+ *
89
+ * @param {String} token
90
+ * @param {String} word
91
+ * @param {Array} collection
92
+ * @return {String}
93
+ */
94
+ function sanitizeWord (token, word, collection) {
95
+ // Empty string or doesn't need fixing.
96
+ if (!token.length || uncountables.hasOwnProperty(token)) {
97
+ return word;
98
+ }
99
+
100
+ var len = collection.length;
101
+
102
+ // Iterate over the sanitization rules and use the first one to match.
103
+ while (len--) {
104
+ var rule = collection[len];
105
+
106
+ // If the rule passes, return the replacement.
107
+ if (rule[0].test(word)) {
108
+ return word.replace(rule[0], function (match, index, word) {
109
+ var result = interpolate(rule[1], arguments);
110
+
111
+ if (match === '') {
112
+ return restoreCase(word[index - 1], result);
113
+ }
114
+
115
+ return restoreCase(match, result);
116
+ });
117
+ }
118
+ }
119
+
120
+ return word;
121
+ }
122
+
123
+ /**
124
+ * Replace a word with the updated word.
125
+ *
126
+ * @param {Object} replaceMap
127
+ * @param {Object} keepMap
128
+ * @param {Array} rules
129
+ * @return {Function}
130
+ */
131
+ function replaceWord (replaceMap, keepMap, rules) {
132
+ return function (word) {
133
+ // Get the correct token and case restoration functions.
134
+ var token = word.toLowerCase();
135
+
136
+ // Check against the keep object map.
137
+ if (keepMap.hasOwnProperty(token)) {
138
+ return restoreCase(word, token);
139
+ }
140
+
141
+ // Check against the replacement map for a direct word replacement.
142
+ if (replaceMap.hasOwnProperty(token)) {
143
+ return restoreCase(word, replaceMap[token]);
144
+ }
145
+
146
+ // Run all the rules against the word.
147
+ return sanitizeWord(token, word, rules);
148
+ };
149
+ }
150
+
151
+ /**
152
+ * Pluralize or singularize a word based on the passed in count.
153
+ *
154
+ * @param {String} word
155
+ * @param {Number} count
156
+ * @param {Boolean} inclusive
157
+ * @return {String}
158
+ */
159
+ function pluralize (word, count, inclusive) {
160
+ var pluralized = count === 1
161
+ ? pluralize.singular(word) : pluralize.plural(word);
162
+
163
+ return (inclusive ? count + ' ' : '') + pluralized;
164
+ }
165
+
166
+ /**
167
+ * Pluralize a word.
168
+ *
169
+ * @type {Function}
170
+ */
171
+ pluralize.plural = replaceWord(
172
+ irregularSingles, irregularPlurals, pluralRules
173
+ );
174
+
175
+ /**
176
+ * Singularize a word.
177
+ *
178
+ * @type {Function}
179
+ */
180
+ pluralize.singular = replaceWord(
181
+ irregularPlurals, irregularSingles, singularRules
182
+ );
183
+
184
+ /**
185
+ * Add a pluralization rule to the collection.
186
+ *
187
+ * @param {(string|RegExp)} rule
188
+ * @param {string} replacement
189
+ */
190
+ pluralize.addPluralRule = function (rule, replacement) {
191
+ pluralRules.push([sanitizeRule(rule), replacement]);
192
+ };
193
+
194
+ /**
195
+ * Add a singularization rule to the collection.
196
+ *
197
+ * @param {(string|RegExp)} rule
198
+ * @param {string} replacement
199
+ */
200
+ pluralize.addSingularRule = function (rule, replacement) {
201
+ singularRules.push([sanitizeRule(rule), replacement]);
202
+ };
203
+
204
+ /**
205
+ * Add an uncountable word rule.
206
+ *
207
+ * @param {(string|RegExp)} word
208
+ */
209
+ pluralize.addUncountableRule = function (word) {
210
+ if (typeof word === 'string') {
211
+ uncountables[word.toLowerCase()] = true;
212
+ return;
213
+ }
214
+
215
+ // Set singular and plural references for the word.
216
+ pluralize.addPluralRule(word, '$0');
217
+ pluralize.addSingularRule(word, '$0');
218
+ };
219
+
220
+ /**
221
+ * Add an irregular word definition.
222
+ *
223
+ * @param {String} single
224
+ * @param {String} plural
225
+ */
226
+ pluralize.addIrregularRule = function (single, plural) {
227
+ plural = plural.toLowerCase();
228
+ single = single.toLowerCase();
229
+
230
+ irregularSingles[single] = plural;
231
+ irregularPlurals[plural] = single;
232
+ };
233
+
234
+ /**
235
+ * Irregular rules.
236
+ */
237
+ [
238
+ // Pronouns.
239
+ ['I', 'we'],
240
+ ['me', 'us'],
241
+ ['he', 'they'],
242
+ ['she', 'they'],
243
+ ['them', 'them'],
244
+ ['myself', 'ourselves'],
245
+ ['yourself', 'yourselves'],
246
+ ['itself', 'themselves'],
247
+ ['herself', 'themselves'],
248
+ ['himself', 'themselves'],
249
+ ['themself', 'themselves'],
250
+ ['is', 'are'],
251
+ ['this', 'these'],
252
+ ['that', 'those'],
253
+ // Words ending in with a consonant and `o`.
254
+ ['echo', 'echoes'],
255
+ ['dingo', 'dingoes'],
256
+ ['volcano', 'volcanoes'],
257
+ ['tornado', 'tornadoes'],
258
+ ['torpedo', 'torpedoes'],
259
+ // Ends with `us`.
260
+ ['genus', 'genera'],
261
+ ['viscus', 'viscera'],
262
+ // Ends with `ma`.
263
+ ['stigma', 'stigmata'],
264
+ ['stoma', 'stomata'],
265
+ ['dogma', 'dogmata'],
266
+ ['lemma', 'lemmata'],
267
+ ['schema', 'schemata'],
268
+ ['anathema', 'anathemata'],
269
+ // Other irregular rules.
270
+ ['ox', 'oxen'],
271
+ ['axe', 'axes'],
272
+ ['die', 'dice'],
273
+ ['yes', 'yeses'],
274
+ ['foot', 'feet'],
275
+ ['eave', 'eaves'],
276
+ ['goose', 'geese'],
277
+ ['tooth', 'teeth'],
278
+ ['quiz', 'quizzes'],
279
+ ['human', 'humans'],
280
+ ['proof', 'proofs'],
281
+ ['carve', 'carves'],
282
+ ['valve', 'valves'],
283
+ ['thief', 'thieves'],
284
+ ['genie', 'genies'],
285
+ ['groove', 'grooves'],
286
+ ['pickaxe', 'pickaxes'],
287
+ ['whiskey', 'whiskies']
288
+ ].forEach(function (rule) {
289
+ return pluralize.addIrregularRule(rule[0], rule[1]);
290
+ });
291
+
292
+ /**
293
+ * Pluralization rules.
294
+ */
295
+ [
296
+ [/s?$/i, 's'],
297
+ [/([^aeiou]ese)$/i, '$1'],
298
+ [/(ax|test)is$/i, '$1es'],
299
+ [/(alias|[^aou]us|tlas|gas|ris)$/i, '$1es'],
300
+ [/(e[mn]u)s?$/i, '$1s'],
301
+ [/([^l]ias|[aeiou]las|[emjzr]as|[iu]am)$/i, '$1'],
302
+ [/(alumn|syllab|octop|vir|radi|nucle|fung|cact|stimul|termin|bacill|foc|uter|loc|strat)(?:us|i)$/i, '$1i'],
303
+ [/(alumn|alg|vertebr)(?:a|ae)$/i, '$1ae'],
304
+ [/(seraph|cherub)(?:im)?$/i, '$1im'],
305
+ [/(her|at|gr)o$/i, '$1oes'],
306
+ [/(agend|addend|millenni|dat|extrem|bacteri|desiderat|strat|candelabr|errat|ov|symposi|curricul|automat|quor)(?:a|um)$/i, '$1a'],
307
+ [/(apheli|hyperbat|periheli|asyndet|noumen|phenomen|criteri|organ|prolegomen|hedr|automat)(?:a|on)$/i, '$1a'],
308
+ [/sis$/i, 'ses'],
309
+ [/(?:(kni|wi|li)fe|(ar|l|ea|eo|oa|hoo)f)$/i, '$1$2ves'],
310
+ [/([^aeiouy]|qu)y$/i, '$1ies'],
311
+ [/([^ch][ieo][ln])ey$/i, '$1ies'],
312
+ [/(x|ch|ss|sh|zz)$/i, '$1es'],
313
+ [/(matr|cod|mur|sil|vert|ind|append)(?:ix|ex)$/i, '$1ices'],
314
+ [/(m|l)(?:ice|ouse)$/i, '$1ice'],
315
+ [/(pe)(?:rson|ople)$/i, '$1ople'],
316
+ [/(child)(?:ren)?$/i, '$1ren'],
317
+ [/eaux$/i, '$0'],
318
+ [/m[ae]n$/i, 'men'],
319
+ ['thou', 'you']
320
+ ].forEach(function (rule) {
321
+ return pluralize.addPluralRule(rule[0], rule[1]);
322
+ });
323
+
324
+ /**
325
+ * Singularization rules.
326
+ */
327
+ [
328
+ [/s$/i, ''],
329
+ [/(ss)$/i, '$1'],
330
+ [/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)(?:sis|ses)$/i, '$1sis'],
331
+ [/(^analy)(?:sis|ses)$/i, '$1sis'],
332
+ [/(wi|kni|(?:after|half|high|low|mid|non|night|[^\w]|^)li)ves$/i, '$1fe'],
333
+ [/(ar|(?:wo|[ae])l|[eo][ao])ves$/i, '$1f'],
334
+ [/([^aeiouy]|qu)ies$/i, '$1y'],
335
+ [/(^[pl]|zomb|^(?:neck)?t|[aeo][lt]|cut)ies$/i, '$1ie'],
336
+ [/(\b(?:mon|smil))ies$/i, '$1ey'],
337
+ [/(m|l)ice$/i, '$1ouse'],
338
+ [/(seraph|cherub)im$/i, '$1'],
339
+ [/(x|ch|ss|sh|zz|tto|go|cho|alias|[^aou]us|tlas|gas|(?:her|at|gr)o|ris)(?:es)?$/i, '$1'],
340
+ [/(e[mn]u)s?$/i, '$1'],
341
+ [/(movie|twelve)s$/i, '$1'],
342
+ [/(cris|test|diagnos)(?:is|es)$/i, '$1is'],
343
+ [/(alumn|syllab|octop|vir|radi|nucle|fung|cact|stimul|termin|bacill|foc|uter|loc|strat)(?:us|i)$/i, '$1us'],
344
+ [/(agend|addend|millenni|dat|extrem|bacteri|desiderat|strat|candelabr|errat|ov|symposi|curricul|quor)a$/i, '$1um'],
345
+ [/(apheli|hyperbat|periheli|asyndet|noumen|phenomen|criteri|organ|prolegomen|hedr|automat)a$/i, '$1on'],
346
+ [/(alumn|alg|vertebr)ae$/i, '$1a'],
347
+ [/(cod|mur|sil|vert|ind)ices$/i, '$1ex'],
348
+ [/(matr|append)ices$/i, '$1ix'],
349
+ [/(pe)(rson|ople)$/i, '$1rson'],
350
+ [/(child)ren$/i, '$1'],
351
+ [/(eau)x?$/i, '$1'],
352
+ [/men$/i, 'man']
353
+ ].forEach(function (rule) {
354
+ return pluralize.addSingularRule(rule[0], rule[1]);
355
+ });
356
+
357
+ /**
358
+ * Uncountable rules.
359
+ */
360
+ [
361
+ // Singular words with no plurals.
362
+ 'advice',
363
+ 'agenda',
364
+ 'bison',
365
+ 'bream',
366
+ 'buffalo',
367
+ 'carp',
368
+ 'chassis',
369
+ 'cod',
370
+ 'cooperation',
371
+ 'corps',
372
+ 'digestion',
373
+ 'debris',
374
+ 'diabetes',
375
+ 'energy',
376
+ 'equipment',
377
+ 'elk',
378
+ 'excretion',
379
+ 'expertise',
380
+ 'flounder',
381
+ 'gallows',
382
+ 'garbage',
383
+ 'graffiti',
384
+ 'headquarters',
385
+ 'health',
386
+ 'herpes',
387
+ 'highjinks',
388
+ 'homework',
389
+ 'information',
390
+ 'jeans',
391
+ 'justice',
392
+ 'kudos',
393
+ 'labour',
394
+ 'machinery',
395
+ 'mackerel',
396
+ 'media',
397
+ 'mews',
398
+ 'moose',
399
+ 'news',
400
+ 'pike',
401
+ 'plankton',
402
+ 'pliers',
403
+ 'pollution',
404
+ 'premises',
405
+ 'rain',
406
+ 'rice',
407
+ 'salmon',
408
+ 'scissors',
409
+ 'series',
410
+ 'sewage',
411
+ 'shambles',
412
+ 'shrimp',
413
+ 'species',
414
+ 'staff',
415
+ 'swine',
416
+ 'trout',
417
+ 'tuna',
418
+ 'whiting',
419
+ 'wildebeest',
420
+ 'wildlife',
421
+ 'you',
422
+ // Regexes.
423
+ /pox$/i, // "chickpox", "smallpox"
424
+ /ois$/i,
425
+ /deer$/i, // "deer", "reindeer"
426
+ /fish$/i, // "fish", "blowfish", "angelfish"
427
+ /sheep$/i,
428
+ /measles$/i,
429
+ /[^aeiou]ese$/i // "chinese", "japanese"
430
+ ].forEach(pluralize.addUncountableRule);
431
+
432
+ return pluralize;
433
+ });
@@ -0,0 +1,11 @@
1
+ - resource_class.reflections.select {|s, r| s and r.macro == :has_many}.each do |symbol, reflection|
2
+ = box do
3
+ = header symbol.to_s.humanize do
4
+ = button "#{t('scaffold.btn.create', :default => 'Create')}", new_polymorphic_path([*parents, resource, symbol.to_s.singularize]) if can? :new, symbol.to_s.singularize.classify.constantize rescue nil
5
+ = button "#{t('scaffold.btn.index', :default => 'Index')}", polymorphic_path([*parents, resource, symbol]) if can? :index, symbol.to_s.singularize.classify.constantize rescue nil
6
+ - controller = "#{symbol.to_s.classify.pluralize}Controller".constantize rescue nil
7
+ = download_mime_type_btns(controller) {|format| polymorphic_path([*parents, resource, symbol], format: format)} if controller and can? :index, symbol.to_s.singularize.classify.constantize #rescue nil
8
+ - array = resource.send(symbol).page(params["page_#{symbol}".to_sym])
9
+ = paginate array, :param_name => "page_#{symbol}".to_sym
10
+ = collection_for array, :parents => [*parents, resource]
11
+ = paginate array, :param_name => "page_#{symbol}".to_sym
File without changes
@@ -0,0 +1,3 @@
1
+ = box do
2
+ = header resource_class.to_s.humanize
3
+ = collection_for resource, :parents => parents