bigpipe-rails 0.0.2

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.
Files changed (78) hide show
  1. data/.document +5 -0
  2. data/.rspec +1 -0
  3. data/Gemfile +20 -0
  4. data/Gemfile.lock +160 -0
  5. data/Guardfile +21 -0
  6. data/LICENSE.txt +20 -0
  7. data/README.md +0 -0
  8. data/README.rdoc +19 -0
  9. data/Rakefile +49 -0
  10. data/VERSION +1 -0
  11. data/assets/bigpipe.coffee +150 -0
  12. data/assets/bigpipe.js +164 -0
  13. data/bigpipe-rails.gemspec +153 -0
  14. data/lib/bigpipe_rails/helper.rb +36 -0
  15. data/lib/bigpipe_rails.rb +13 -0
  16. data/lib/engines.rb +16 -0
  17. data/qunit/.DS_Store +0 -0
  18. data/qunit/qunit.css +227 -0
  19. data/qunit/qunit.js +1450 -0
  20. data/qunit/tests.html +302 -0
  21. data/spec/dummy_app/.gitignore +5 -0
  22. data/spec/dummy_app/Gemfile +19 -0
  23. data/spec/dummy_app/Gemfile.lock +143 -0
  24. data/spec/dummy_app/README +261 -0
  25. data/spec/dummy_app/Rakefile +7 -0
  26. data/spec/dummy_app/app/assets/images/rails.png +0 -0
  27. data/spec/dummy_app/app/assets/javascripts/application.js +5 -0
  28. data/spec/dummy_app/app/assets/stylesheets/application.css +7 -0
  29. data/spec/dummy_app/app/controllers/application_controller.rb +3 -0
  30. data/spec/dummy_app/app/controllers/test_controller.rb +8 -0
  31. data/spec/dummy_app/app/helpers/application_helper.rb +2 -0
  32. data/spec/dummy_app/app/mailers/.gitkeep +0 -0
  33. data/spec/dummy_app/app/models/.gitkeep +0 -0
  34. data/spec/dummy_app/app/views/layouts/application.html.erb +18 -0
  35. data/spec/dummy_app/app/views/test/test.html.erb +3 -0
  36. data/spec/dummy_app/app/views/test/test_with_exception.html.erb +7 -0
  37. data/spec/dummy_app/config/application.rb +47 -0
  38. data/spec/dummy_app/config/boot.rb +6 -0
  39. data/spec/dummy_app/config/database.yml +25 -0
  40. data/spec/dummy_app/config/environment.rb +5 -0
  41. data/spec/dummy_app/config/environments/development.rb +27 -0
  42. data/spec/dummy_app/config/environments/production.rb +54 -0
  43. data/spec/dummy_app/config/environments/test.rb +39 -0
  44. data/spec/dummy_app/config/initializers/backtrace_silencers.rb +7 -0
  45. data/spec/dummy_app/config/initializers/inflections.rb +10 -0
  46. data/spec/dummy_app/config/initializers/mime_types.rb +5 -0
  47. data/spec/dummy_app/config/initializers/secret_token.rb +7 -0
  48. data/spec/dummy_app/config/initializers/session_store.rb +8 -0
  49. data/spec/dummy_app/config/initializers/wrap_parameters.rb +12 -0
  50. data/spec/dummy_app/config/locales/en.yml +5 -0
  51. data/spec/dummy_app/config/routes.rb +62 -0
  52. data/spec/dummy_app/config/unicorn.rb +1 -0
  53. data/spec/dummy_app/config.ru +4 -0
  54. data/spec/dummy_app/db/seeds.rb +7 -0
  55. data/spec/dummy_app/lib/tasks/.gitkeep +0 -0
  56. data/spec/dummy_app/log/.gitkeep +0 -0
  57. data/spec/dummy_app/public/404.html +26 -0
  58. data/spec/dummy_app/public/422.html +26 -0
  59. data/spec/dummy_app/public/500.html +26 -0
  60. data/spec/dummy_app/public/favicon.ico +0 -0
  61. data/spec/dummy_app/public/index.html +241 -0
  62. data/spec/dummy_app/public/javascripts/bigpipe.js +164 -0
  63. data/spec/dummy_app/public/robots.txt +5 -0
  64. data/spec/dummy_app/script/rails +6 -0
  65. data/spec/dummy_app/spec/spec_helper.rb +26 -0
  66. data/spec/dummy_app/test/fixtures/.gitkeep +0 -0
  67. data/spec/dummy_app/test/functional/.gitkeep +0 -0
  68. data/spec/dummy_app/test/integration/.gitkeep +0 -0
  69. data/spec/dummy_app/test/integration/testabc_test.rb +9 -0
  70. data/spec/dummy_app/test/performance/browsing_test.rb +12 -0
  71. data/spec/dummy_app/test/test_helper.rb +13 -0
  72. data/spec/dummy_app/test/unit/.gitkeep +0 -0
  73. data/spec/dummy_app/vendor/assets/stylesheets/.gitkeep +0 -0
  74. data/spec/dummy_app/vendor/plugins/.gitkeep +0 -0
  75. data/spec/lib/bigpipe_rails_spec.rb +18 -0
  76. data/spec/requests/bigpipe_request_spec.rb +21 -0
  77. data/spec/spec_helper.rb +28 -0
  78. metadata +277 -0
data/qunit/tests.html ADDED
@@ -0,0 +1,302 @@
1
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
2
+ "http://www.w3.org/TR/html4/loose.dtd">
3
+ <html>
4
+ <head>
5
+ <script src="http://code.jquery.com/jquery-latest.js"></script>
6
+ <script src="../assets/bigpipe.js"></script>
7
+ <link rel="stylesheet" href="qunit.css" type="text/css" media="screen" />
8
+ <script type="text/javascript" src="qunit.js"></script>
9
+
10
+ <script>
11
+ $j(document).ready(function(){
12
+
13
+ module("Bigpipe");
14
+
15
+ test("instance variable initialization", function() {
16
+ equals( Bigpipe.pagelets.length, 0, "initialized with an empty array" );
17
+
18
+ ok( $j.isEmptyObject(Bigpipe.css), "initialized with an empty object" );
19
+ ok( $j.isEmptyObject(Bigpipe.js), "initialized with an empty object" );
20
+ });
21
+
22
+ module("Pagelet");
23
+
24
+ test("pagelet initialization", function () {
25
+ data = {
26
+ container: "#my_container",
27
+ content : "<p>Heya!</p>",
28
+ append : true
29
+ };
30
+
31
+ Bigpipe.add_pagelet(data);
32
+
33
+ equals( Bigpipe.pagelets.length, 1, "the pagelet resource created" );
34
+
35
+ pagelet = Bigpipe.pagelets[0];
36
+
37
+ equals( pagelet.container, "#my_container", "the container instance variable initialized correctly" );
38
+ equals( pagelet.content, "<p>Heya!</p>", "the content instance variable initialized correctly" );
39
+ equals( pagelet.append, true, "the append instance variable initialized correctly" );
40
+ equals( $j.type(pagelet.on_load), "function", "on_load initialized correctly" );
41
+
42
+ equals( pagelet.js_resources.length, 0, "no js resources were specified so none were created" );
43
+ equals( pagelet.css_resources.length, 0, "no css resources were specified so none were created" );
44
+ });
45
+
46
+ test("single CssResource creation", function () {
47
+ data = {
48
+ container: "#my_container",
49
+ content : "<p>Heya!</p>",
50
+ css : ["my_css"]
51
+ };
52
+
53
+ Bigpipe.add_pagelet(data);
54
+ setTimeout(function(){}, 200); // let the resource load to completion, ie load_phase 2
55
+
56
+ ok( Bigpipe.css["my_css"], "the css resource was created" );
57
+ equals( Bigpipe.css["my_css"].file_name, "my_css", "the css resource has the correct filename" );
58
+ equals( Bigpipe.css["my_css"].load_phase, 2, "the css resource fully loaded" );
59
+
60
+ element = Bigpipe.css["my_css"].el;
61
+
62
+ equals(element.attr('rel'), "stylesheet");
63
+ equals(element.attr('href'), "my_css.css");
64
+ });
65
+
66
+ test("single JsResource creation", function () {
67
+ data = {
68
+ container: "#my_container",
69
+ content : "<p>Heya!</p>",
70
+ js : ["my_js"]
71
+ };
72
+
73
+ Bigpipe.add_pagelet(data);
74
+ setTimeout(function(){}, 200); // let the resource load to completion, ie load_phase 2
75
+
76
+ ok( Bigpipe.js["my_js"], "the js resource was created" );
77
+ equals( Bigpipe.js["my_js"].file_name, "my_js", "the js resource has the correct filename" );
78
+
79
+ equals( Bigpipe.js["my_js"].load_phase, 2, "the js resource fully loaded" );
80
+
81
+ element = Bigpipe.js["my_js"].el;
82
+
83
+ equals(element.attr('type'), "text/javascript");
84
+ equals(element.attr('src'), "my_js.js");
85
+ });
86
+
87
+ test("multiple CssResource creation", function () {
88
+ var i, file_name;
89
+ var file_names = [];
90
+
91
+ file_names = ["my_css1", "my_css2", "my_css3"]
92
+
93
+ data = {
94
+ container: "#my_container",
95
+ content : "<p>Heya!</p>",
96
+ css : file_names
97
+ };
98
+
99
+ Bigpipe.add_pagelet(data);
100
+ setTimeout(function(){}, 200); // let the resource load to completion, ie load_phase 2
101
+
102
+ for(i = 0; i < file_names.length; i++) {
103
+ file_name = file_names[i];
104
+
105
+ ok( Bigpipe.css[file_name], "the css resource was created" );
106
+ equals( Bigpipe.css[file_name].file_name, file_name, "the css resource has the correct filename" );
107
+
108
+ equals( Bigpipe.css[file_name].load_phase, 2, "the css resource fully loaded" );
109
+
110
+ element = Bigpipe.css[file_name].el;
111
+
112
+ equals(element.attr('rel'), "stylesheet");
113
+ equals(element.attr('href'), file_name + ".css");
114
+ }
115
+ });
116
+
117
+ test("multiple JsResource creation", function () {
118
+ var i, file_name;
119
+ var file_names = [];
120
+
121
+ file_names = ["my_js1", "my_js2", "my_js3"]
122
+
123
+ data = {
124
+ container: "#my_container",
125
+ content : "<p>Heya!</p>",
126
+ js : file_names
127
+ };
128
+
129
+ Bigpipe.add_pagelet(data);
130
+ setTimeout(function(){}, 200); // let the resource load to completion, ie load_phase 2
131
+
132
+ for(i = 0; i < file_names.length; i++) {
133
+ file_name = file_names[i];
134
+
135
+ ok( Bigpipe.js[file_name], "the js resource was created" );
136
+ equals( Bigpipe.js[file_name].file_name, file_name, "the js resource has the correct filename" );
137
+
138
+ equals( Bigpipe.js[file_name].load_phase, 2, "the js resource fully loaded" );
139
+
140
+ element = Bigpipe.js[file_name].el;
141
+
142
+ equals(element.attr('type'), "text/javascript");
143
+ equals(element.attr('src'), file_name + ".js");
144
+ }
145
+ });
146
+
147
+ test("multiple CssResource and JsResource creation", function () {
148
+ var i = 0;
149
+ var file_name = "";
150
+ var css_file_names = [];
151
+ var js_file_names = [];
152
+
153
+ js_file_names = ["my_js1", "my_js2", "my_js3"];
154
+ css_file_names = ["my_css1", "my_css2", "my_css3"];
155
+ data = {
156
+ container : "#my_container",
157
+ content : "<p>Heya!</p>",
158
+ js : js_file_names,
159
+ css : css_file_names
160
+ };
161
+
162
+ Bigpipe.add_pagelet(data);
163
+ setTimeout(function(){}, 200); // let the resource load to completion, ie load_phase 2
164
+
165
+ for(i = 0; i < js_file_names.length; i++) {
166
+ file_name = js_file_names[i];
167
+
168
+ ok( Bigpipe.js[file_name], "the js resource was created" );
169
+ equals( Bigpipe.js[file_name].file_name, file_name, "the js resource has the correct filename" );
170
+
171
+ equals( Bigpipe.js[file_name].load_phase, 2, "the js resource fully loaded" );
172
+
173
+ element = Bigpipe.js[file_name].el;
174
+
175
+ equals(element.attr('type'), "text/javascript");
176
+ equals(element.attr('src'), file_name + ".js");
177
+ }
178
+
179
+ for(i = 0; i < css_file_names.length; i++) {
180
+ file_name = css_file_names[i];
181
+
182
+ ok( Bigpipe.css[file_name], "the css resource was created" );
183
+ equals( Bigpipe.css[file_name].file_name, file_name, "the css resource has the correct filename" );
184
+
185
+ equals( Bigpipe.css[file_name].load_phase, 2, "the css resource fully loaded" );
186
+
187
+ element = Bigpipe.css[file_name].el;
188
+
189
+ equals(element.attr('rel'), "stylesheet");
190
+ equals(element.attr('href'), file_name + ".css");
191
+ }
192
+ });
193
+
194
+ test("creating two pagelets with different resource types", function () {
195
+ pagelet1_data = {
196
+ container: "#my_container1",
197
+ content : "<p>Pagelet with a js resource</p>",
198
+ js : "my_js"
199
+ };
200
+
201
+ pagelet2_data = {
202
+ container: "#my_container2",
203
+ content : "<p>Pagelet with a css resource</p>",
204
+ css : "my_css"
205
+ }
206
+
207
+ Bigpipe.add_pagelet(pagelet1_data);
208
+ Bigpipe.add_pagelet(pagelet2_data);
209
+ setTimeout(function(){}, 200); // let the resource load to completion, ie load_phase 2
210
+
211
+ // Test the pagelet with the JS resource
212
+ ok( Bigpipe.js["my_js"], "the js resource was created" );
213
+ equals( Bigpipe.js["my_js"].file_name, "my_js", "the js resource has the correct filename" );
214
+
215
+ equals( Bigpipe.js["my_js"].load_phase, 2, "the js resource fully loaded" );
216
+
217
+ element = Bigpipe.js["my_js"].el;
218
+
219
+ equals(element.attr('type'), "text/javascript");
220
+ equals(element.attr('src'), "my_js.js");
221
+
222
+ // Test the pagelet with the CSS resource
223
+ ok( Bigpipe.css["my_css"], "the css resource was created" );
224
+ equals( Bigpipe.css["my_css"].file_name, "my_css", "the css resource has the correct filename" );
225
+ equals( Bigpipe.css["my_css"].load_phase, 2, "the css resource fully loaded" );
226
+
227
+ element = Bigpipe.css["my_css"].el;
228
+
229
+ equals(element.attr('rel'), "stylesheet");
230
+ equals(element.attr('href'), "my_css.css");
231
+ });
232
+
233
+ test("creating multiple pagelets with both types of resources", function () {
234
+ pagelet1_css_file_names = ["my_css1", "my_css2"]
235
+ pagelet1_js_file_names = ["my_js1", "my_js2"]
236
+
237
+ pagelet2_css_file_names = ["my_css3", "my_css4"]
238
+ pagelet2_js_file_names = ["my_js3", "my_js4"]
239
+
240
+ pagelet1_data = {
241
+ container: "#my_container1",
242
+ content : "<p>Pagelet 1 content</p>",
243
+ css : pagelet1_css_file_names,
244
+ js : pagelet1_js_file_names
245
+ };
246
+
247
+ pagelet2_data = {
248
+ container: "#my_container2",
249
+ content : "<p>Pagelet 2 content</p>",
250
+ css : pagelet2_css_file_names,
251
+ js : pagelet2_js_file_names
252
+ };
253
+
254
+ css_file_names = pagelet1_css_file_names.concat(pagelet2_css_file_names);
255
+ js_file_names = pagelet1_js_file_names.concat(pagelet2_js_file_names);
256
+
257
+ Bigpipe.add_pagelet(pagelet1_data);
258
+ Bigpipe.add_pagelet(pagelet2_data);
259
+ setTimeout(function(){}, 200); // let the resource load to completion, ie load_phase 2
260
+
261
+ for(i = 0; i < js_file_names.length; i++) {
262
+ file_name = js_file_names[i];
263
+
264
+ ok( Bigpipe.js[file_name], "the js resource was created" );
265
+ equals( Bigpipe.js[file_name].file_name, file_name, "the js resource has the correct filename" );
266
+
267
+ equals( Bigpipe.js[file_name].load_phase, 2, "the js resource fully loaded" );
268
+
269
+ element = Bigpipe.js[file_name].el;
270
+
271
+ equals(element.attr('type'), "text/javascript");
272
+ equals(element.attr('src'), file_name + ".js");
273
+ }
274
+
275
+ for(i = 0; i < css_file_names.length; i++) {
276
+ file_name = css_file_names[i];
277
+
278
+ ok( Bigpipe.css[file_name], "the css resource was created" );
279
+ equals( Bigpipe.css[file_name].file_name, file_name, "the css resource has the correct filename" );
280
+
281
+ equals( Bigpipe.css[file_name].load_phase, 2, "the css resource fully loaded" );
282
+
283
+ element = Bigpipe.css[file_name].el;
284
+
285
+ equals(element.attr('rel'), "stylesheet");
286
+ equals(element.attr('href'), file_name + ".css");
287
+ }
288
+ });
289
+ });
290
+ </script>
291
+
292
+ </head>
293
+ <body>
294
+ <h1 id="qunit-header">Big Pipe</h1>
295
+ <h2 id="qunit-banner"></h2>
296
+ <div id="qunit-testrunner-toolbar"></div>
297
+ <h2 id="qunit-userAgent"></h2>
298
+ <ol id="qunit-tests"></ol>
299
+ <div id="qunit-fixture">test markup, will be hidden</div>
300
+ </body>
301
+ </html>
302
+
@@ -0,0 +1,5 @@
1
+ .bundle
2
+ db/*.sqlite3
3
+ log/*.log
4
+ tmp/
5
+ .sass-cache/
@@ -0,0 +1,19 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gem 'rails', '3.1.0.rc4'
4
+ gem 'sqlite3'
5
+ gem 'bigpipe-rails'
6
+
7
+ # Bundle gems for the local environment. Make sure to
8
+ # put test-only gems in this group so their generators
9
+ # and rake tasks are available in development mode:
10
+ group :development, :test do
11
+ gem 'ruby-debug19', :require => 'ruby-debug'
12
+ gem 'rspec-rails'
13
+ gem 'guard-rspec'
14
+ gem 'mocha'
15
+ gem 'unicorn'
16
+ gem 'factory_girl_rails'
17
+ gem 'rails3-generators'
18
+ gem 'growl'
19
+ end
@@ -0,0 +1,143 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ actionmailer (3.1.0.rc4)
5
+ actionpack (= 3.1.0.rc4)
6
+ mail (~> 2.3.0)
7
+ actionpack (3.1.0.rc4)
8
+ activemodel (= 3.1.0.rc4)
9
+ activesupport (= 3.1.0.rc4)
10
+ builder (~> 3.0.0)
11
+ erubis (~> 2.7.0)
12
+ i18n (~> 0.6)
13
+ rack (~> 1.3.0)
14
+ rack-cache (~> 1.0.1)
15
+ rack-mount (~> 0.8.1)
16
+ rack-test (~> 0.6.0)
17
+ sprockets (~> 2.0.0.beta.10)
18
+ tzinfo (~> 0.3.27)
19
+ activemodel (3.1.0.rc4)
20
+ activesupport (= 3.1.0.rc4)
21
+ bcrypt-ruby (~> 2.1.4)
22
+ builder (~> 3.0.0)
23
+ i18n (~> 0.6)
24
+ activerecord (3.1.0.rc4)
25
+ activemodel (= 3.1.0.rc4)
26
+ activesupport (= 3.1.0.rc4)
27
+ arel (~> 2.1.1)
28
+ tzinfo (~> 0.3.27)
29
+ activeresource (3.1.0.rc4)
30
+ activemodel (= 3.1.0.rc4)
31
+ activesupport (= 3.1.0.rc4)
32
+ activesupport (3.1.0.rc4)
33
+ multi_json (~> 1.0)
34
+ archive-tar-minitar (0.5.2)
35
+ arel (2.1.3)
36
+ bcrypt-ruby (2.1.4)
37
+ builder (3.0.0)
38
+ columnize (0.3.4)
39
+ diff-lcs (1.1.2)
40
+ erubis (2.7.0)
41
+ factory_girl (2.0.1)
42
+ factory_girl_rails (1.1.0)
43
+ factory_girl (~> 2.0.0)
44
+ railties (>= 3.0.0)
45
+ growl (1.0.3)
46
+ guard (0.5.1)
47
+ thor (~> 0.14.6)
48
+ guard-rspec (0.4.0)
49
+ guard (>= 0.4.0)
50
+ hike (1.2.0)
51
+ i18n (0.6.0)
52
+ kgio (2.6.0)
53
+ linecache19 (0.5.12)
54
+ ruby_core_source (>= 0.1.4)
55
+ mail (2.3.0)
56
+ i18n (>= 0.4.0)
57
+ mime-types (~> 1.16)
58
+ treetop (~> 1.4.8)
59
+ mime-types (1.16)
60
+ mocha (0.9.12)
61
+ multi_json (1.0.3)
62
+ polyglot (0.3.1)
63
+ rack (1.3.1)
64
+ rack-cache (1.0.2)
65
+ rack (>= 0.4)
66
+ rack-mount (0.8.1)
67
+ rack (>= 1.0.0)
68
+ rack-ssl (1.3.2)
69
+ rack
70
+ rack-test (0.6.0)
71
+ rack (>= 1.0)
72
+ rails (3.1.0.rc4)
73
+ actionmailer (= 3.1.0.rc4)
74
+ actionpack (= 3.1.0.rc4)
75
+ activerecord (= 3.1.0.rc4)
76
+ activeresource (= 3.1.0.rc4)
77
+ activesupport (= 3.1.0.rc4)
78
+ bundler (~> 1.0)
79
+ railties (= 3.1.0.rc4)
80
+ rails3-generators (0.17.4)
81
+ railties (>= 3.0.0)
82
+ railties (3.1.0.rc4)
83
+ actionpack (= 3.1.0.rc4)
84
+ activesupport (= 3.1.0.rc4)
85
+ rack-ssl (~> 1.3.2)
86
+ rake (>= 0.8.7)
87
+ rdoc (~> 3.4)
88
+ thor (~> 0.14.6)
89
+ raindrops (0.7.0)
90
+ rake (0.9.2)
91
+ rdoc (3.8)
92
+ rspec (2.6.0)
93
+ rspec-core (~> 2.6.0)
94
+ rspec-expectations (~> 2.6.0)
95
+ rspec-mocks (~> 2.6.0)
96
+ rspec-core (2.6.4)
97
+ rspec-expectations (2.6.0)
98
+ diff-lcs (~> 1.1.2)
99
+ rspec-mocks (2.6.0)
100
+ rspec-rails (2.6.1)
101
+ actionpack (~> 3.0)
102
+ activesupport (~> 3.0)
103
+ railties (~> 3.0)
104
+ rspec (~> 2.6.0)
105
+ ruby-debug-base19 (0.11.25)
106
+ columnize (>= 0.3.1)
107
+ linecache19 (>= 0.5.11)
108
+ ruby_core_source (>= 0.1.4)
109
+ ruby-debug19 (0.11.6)
110
+ columnize (>= 0.3.1)
111
+ linecache19 (>= 0.5.11)
112
+ ruby-debug-base19 (>= 0.11.19)
113
+ ruby_core_source (0.1.5)
114
+ archive-tar-minitar (>= 0.5.2)
115
+ sprockets (2.0.0.beta.10)
116
+ hike (~> 1.0)
117
+ rack (~> 1.0)
118
+ tilt (!= 1.3.0, ~> 1.1)
119
+ sqlite3 (1.3.3)
120
+ thor (0.14.6)
121
+ tilt (1.3.2)
122
+ treetop (1.4.9)
123
+ polyglot (>= 0.3.1)
124
+ tzinfo (0.3.29)
125
+ unicorn (4.0.1)
126
+ kgio (~> 2.4)
127
+ rack
128
+ raindrops (~> 0.6)
129
+
130
+ PLATFORMS
131
+ ruby
132
+
133
+ DEPENDENCIES
134
+ factory_girl_rails
135
+ growl
136
+ guard-rspec
137
+ mocha
138
+ rails (= 3.1.0.rc4)
139
+ rails3-generators
140
+ rspec-rails
141
+ ruby-debug19
142
+ sqlite3
143
+ unicorn