e 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (169) hide show
  1. data/.travis.yml +6 -0
  2. data/CHANGELOG.md +74 -0
  3. data/Gemfile +10 -0
  4. data/LICENSE +19 -0
  5. data/README.md +461 -0
  6. data/Rakefile +58 -0
  7. data/docs/Deploy.md +296 -0
  8. data/docs/Intro.md +179 -0
  9. data/docs/Routing.md +677 -0
  10. data/docs/Setup.md +286 -0
  11. data/docs/Streaming.md +139 -0
  12. data/docs/ViewAPI.md +493 -0
  13. data/docs/Workflow.md +1240 -0
  14. data/e.gemspec +25 -0
  15. data/lib/e-builder.rb +2 -0
  16. data/lib/e-builder/base.rb +355 -0
  17. data/lib/e-builder/setup.rb +238 -0
  18. data/lib/e-core.rb +28 -0
  19. data/lib/e-core/constants.rb +74 -0
  20. data/lib/e-core/controller/actions.rb +128 -0
  21. data/lib/e-core/controller/mounter.rb +339 -0
  22. data/lib/e-core/controller/setups_reader.rb +95 -0
  23. data/lib/e-core/controller/setups_writer.rb +347 -0
  24. data/lib/e-core/e-core.rb +56 -0
  25. data/lib/e-core/instance/base.rb +199 -0
  26. data/lib/e-core/instance/cookies.rb +55 -0
  27. data/lib/e-core/instance/halt.rb +89 -0
  28. data/lib/e-core/instance/helpers.rb +78 -0
  29. data/lib/e-core/instance/invoke.rb +127 -0
  30. data/lib/e-core/instance/redirect.rb +43 -0
  31. data/lib/e-core/instance/request.rb +66 -0
  32. data/lib/e-core/instance/response.rb +54 -0
  33. data/lib/e-core/instance/send_file.rb +44 -0
  34. data/lib/e-core/instance/session.rb +64 -0
  35. data/lib/e-core/instance/setup/auth.rb +224 -0
  36. data/lib/e-core/instance/setup/generic.rb +209 -0
  37. data/lib/e-core/instance/stream.rb +155 -0
  38. data/lib/e-core/rewriter.rb +71 -0
  39. data/lib/e-core/utils.rb +178 -0
  40. data/lib/e-ext.rb +26 -0
  41. data/lib/e-more.rb +3 -0
  42. data/lib/e-more/view.rb +8 -0
  43. data/lib/e-more/view/base.rb +205 -0
  44. data/lib/e-more/view/constants.rb +46 -0
  45. data/lib/e-more/view/e-builder.rb +37 -0
  46. data/lib/e-more/view/setup.rb +123 -0
  47. data/lib/e-more/view/utils.rb +19 -0
  48. data/lib/e-version.rb +6 -0
  49. data/lib/e-version.rb~ +6 -0
  50. data/lib/e.rb +4 -0
  51. data/test/e-core/test__3rd_party_apps.rb +98 -0
  52. data/test/e-core/test__accept.rb +55 -0
  53. data/test/e-core/test__action_alias.rb +96 -0
  54. data/test/e-core/test__action_name.rb +41 -0
  55. data/test/e-core/test__alias.rb +37 -0
  56. data/test/e-core/test__app_auth.rb +94 -0
  57. data/test/e-core/test__app_map.rb +47 -0
  58. data/test/e-core/test__around.rb +24 -0
  59. data/test/e-core/test__auth.rb +161 -0
  60. data/test/e-core/test__automount.rb +29 -0
  61. data/test/e-core/test__builtin_helpers.rb +35 -0
  62. data/test/e-core/test__cache_control.rb +62 -0
  63. data/test/e-core/test__canonical.rb +73 -0
  64. data/test/e-core/test__charset.rb +59 -0
  65. data/test/e-core/test__content_type.rb +54 -0
  66. data/test/e-core/test__cookies.rb +40 -0
  67. data/test/e-core/test__error.rb +44 -0
  68. data/test/e-core/test__expires.rb +78 -0
  69. data/test/e-core/test__file.rb +30 -0
  70. data/test/e-core/test__files.rb +21 -0
  71. data/test/e-core/test__format.rb +111 -0
  72. data/test/e-core/test__halt.rb +50 -0
  73. data/test/e-core/test__helpers.rb +24 -0
  74. data/test/e-core/test__host.rb +91 -0
  75. data/test/e-core/test__import.rb +46 -0
  76. data/test/e-core/test__invoke.rb +162 -0
  77. data/test/e-core/test__last_modified.rb +56 -0
  78. data/test/e-core/test__mount.rb +99 -0
  79. data/test/e-core/test__params.rb +110 -0
  80. data/test/e-core/test__path_rules.rb +83 -0
  81. data/test/e-core/test__redirect.rb +105 -0
  82. data/test/e-core/test__rest.rb +106 -0
  83. data/test/e-core/test__rewriter.rb +231 -0
  84. data/test/e-core/test__router.rb +171 -0
  85. data/test/e-core/test__session.rb +69 -0
  86. data/test/e-core/test__setup.rb +83 -0
  87. data/test/e-core/test__setup_aliases.rb +66 -0
  88. data/test/e-core/test__subcontrollers.rb +45 -0
  89. data/test/e-core/test__transfer_encoding.rb +51 -0
  90. data/test/e-core/test__utils.rb +51 -0
  91. data/test/e-more/view/custom-templates/layout.erb +5 -0
  92. data/test/e-more/view/custom-templates/some-file.erb +1 -0
  93. data/test/e-more/view/custom-templates/some_partial.erb +1 -0
  94. data/test/e-more/view/templates/adhoc_test/custom_layout.erb +1 -0
  95. data/test/e-more/view/templates/adhoc_test/index.erb +1 -0
  96. data/test/e-more/view/templates/adhoc_test/index.html.erb +1 -0
  97. data/test/e-more/view/templates/adhoc_test/layouts/custom.erb +1 -0
  98. data/test/e-more/view/templates/adhoc_test/layouts/master.erb +1 -0
  99. data/test/e-more/view/templates/adhoc_test/layouts/named.erb +1 -0
  100. data/test/e-more/view/templates/adhoc_test/layouts/slim_layout_file.slim +5 -0
  101. data/test/e-more/view/templates/adhoc_test/partial.erb +1 -0
  102. data/test/e-more/view/templates/adhoc_test/partial.html.erb +1 -0
  103. data/test/e-more/view/templates/adhoc_test/rabl_file.rabl +2 -0
  104. data/test/e-more/view/templates/adhoc_test/slim_file.slim +1 -0
  105. data/test/e-more/view/templates/blah.erb +1 -0
  106. data/test/e-more/view/templates/canonical_test/index.erb +1 -0
  107. data/test/e-more/view/templates/e_more_test__view__view_prefix/default/index.erb +1 -0
  108. data/test/e-more/view/templates/e_more_test__view__view_prefix/nested/app/index.erb +1 -0
  109. data/test/e-more/view/templates/engine_ext_test/blah.xml.str +1 -0
  110. data/test/e-more/view/templates/engine_ext_test/custom___ext.xhtml +1 -0
  111. data/test/e-more/view/templates/engine_ext_test/custom___ext.xml.xhtml +1 -0
  112. data/test/e-more/view/templates/engine_ext_test/slim.html.slm +1 -0
  113. data/test/e-more/view/templates/engine_ext_test/slim.slm +1 -0
  114. data/test/e-more/view/templates/engine_test/blah.haml +1 -0
  115. data/test/e-more/view/templates/engine_test/blah.txt.slim +1 -0
  116. data/test/e-more/view/templates/engine_test/blah.xml.str +1 -0
  117. data/test/e-more/view/templates/engine_test/index.haml +1 -0
  118. data/test/e-more/view/templates/engine_test/index.xml.erb +1 -0
  119. data/test/e-more/view/templates/format_test/api.json.erb +1 -0
  120. data/test/e-more/view/templates/format_test/index.erb +1 -0
  121. data/test/e-more/view/templates/format_test/index.html.erb +1 -0
  122. data/test/e-more/view/templates/format_test/index.xml.erb +1 -0
  123. data/test/e-more/view/templates/format_test/string.erb +1 -0
  124. data/test/e-more/view/templates/format_test/string.str.str +1 -0
  125. data/test/e-more/view/templates/generic_test/custom___ext.xhtml +1 -0
  126. data/test/e-more/view/templates/generic_test/custom___ext.xml.xhtml +1 -0
  127. data/test/e-more/view/templates/generic_test/get_partial.erb +1 -0
  128. data/test/e-more/view/templates/generic_test/implicit_template_with_custom_context.erb +1 -0
  129. data/test/e-more/view/templates/generic_test/implicit_template_with_custom_locals.erb +1 -0
  130. data/test/e-more/view/templates/generic_test/index.erb +1 -0
  131. data/test/e-more/view/templates/generic_test/some___action.erb +1 -0
  132. data/test/e-more/view/templates/layout.erb +1 -0
  133. data/test/e-more/view/templates/layout.haml +2 -0
  134. data/test/e-more/view/templates/layout.txt.slim +3 -0
  135. data/test/e-more/view/templates/layout.xml.erb +1 -0
  136. data/test/e-more/view/templates/layout__custom_context.erb +1 -0
  137. data/test/e-more/view/templates/layout__custom_locals.erb +1 -0
  138. data/test/e-more/view/templates/layout__format.erb +1 -0
  139. data/test/e-more/view/templates/layout__format.html.erb +1 -0
  140. data/test/e-more/view/templates/layout__format.xml.erb +1 -0
  141. data/test/e-more/view/templates/layouts/_header.erb +1 -0
  142. data/test/e-more/view/templates/layouts/base.erb +1 -0
  143. data/test/e-more/view/templates/path_test/index.erb +1 -0
  144. data/test/e-more/view/templates/path_test/partial.erb +1 -0
  145. data/test/e-more/view/templates/rabl_test/index.rabl +1 -0
  146. data/test/e-more/view/templates/relpath_test/blah.erb +1 -0
  147. data/test/e-more/view/templates/relpath_test/index.erb +1 -0
  148. data/test/e-more/view/templates/relpath_test/partial.erb +1 -0
  149. data/test/e-more/view/templates/render_file.rabl +2 -0
  150. data/test/e-more/view/templates/render_file.slim +1 -0
  151. data/test/e-more/view/templates/render_layout_file.slim +5 -0
  152. data/test/e-more/view/templates/slim_test/index.slim +1 -0
  153. data/test/e-more/view/test__adhoc_render.rb +144 -0
  154. data/test/e-more/view/test__engine.rb +55 -0
  155. data/test/e-more/view/test__engine_ext.rb +56 -0
  156. data/test/e-more/view/test__format.rb +101 -0
  157. data/test/e-more/view/test__generic.rb +153 -0
  158. data/test/e-more/view/test__path.rb +49 -0
  159. data/test/e-more/view/test__rabl.rb +20 -0
  160. data/test/e-more/view/test__relpath.rb +71 -0
  161. data/test/e-more/view/test__render_file.rb +92 -0
  162. data/test/e-more/view/test__render_layout.rb +126 -0
  163. data/test/e-more/view/test__slim.rb +20 -0
  164. data/test/e-more/view/test__view_prefix.rb +76 -0
  165. data/test/overhead/espresso-app.rb +11 -0
  166. data/test/overhead/run.rb +56 -0
  167. data/test/setup.rb +14 -0
  168. data/test/support/http_spec_helper.rb +56 -0
  169. metadata +262 -0
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - 2.0.0
5
+ - jruby-19mode
6
+ - rbx-19mode
@@ -0,0 +1,74 @@
1
+
2
+ + 0.4.7 [May 25 2013]
3
+ - `on_boot` hook for applications - [543e032](https://github.com/espresso/espresso/commit/543e032)
4
+ - Allow controllers to mount sub-controllers - [203c314](https://github.com/espresso/espresso/commit/203c314)
5
+ - Canonicals can not be passed at mounting anymore.
6
+ - `evented_stream` and `chunked_stream` helpers - [aebc298](https://github.com/espresso/espresso/commit/aebc298)
7
+ - `styled_halt` helper - [5eeb404190](https://github.com/espresso/espresso/commit/5eeb404190)
8
+ - `mapped?` helper - [d0ee33729](https://github.com/espresso/espresso/commit/d0ee33729)
9
+ - `view_path_proxy` helper renamed into `explicit_view_path`
10
+
11
+ <hr>
12
+
13
+ + 0.4.6 [Apr 25 2013]
14
+ - Added token based authorization - [1beb5db](https://github.com/espresso/espresso/commit/1beb5db)
15
+ - Respond only to requests originating on known hosts - [f2d1027](https://github.com/espresso/espresso/commit/f2d10)
16
+ - Allow mounting of any Rack application - [bb3ff2](https://github.com/espresso/espresso/commit/bb3ff2)
17
+
18
+ <hr>
19
+
20
+ + 0.4.5 [Apr 11 2013]
21
+ - Deprecating `EspressoApp`. Now applications are built via `E.new`
22
+ - Moving CRUD, Assets, HTMLHelpers, Cache and IPCM extensions to a separate gem
23
+ - Added `around` filter
24
+ - Removing `helper` method. `include` are now used to share helpers between controllers and `import` to share actions.
25
+
26
+ <hr>
27
+
28
+ + 0.4.3 [March 20 2013]
29
+ - View compiler enabled by default - [2baaf2](https://github.com/espresso/espresso/commit/2baaf2)
30
+ - Rabl support added - [f65a37bb059](https://github.com/espresso/espresso/commit/f65a37bb059)
31
+
32
+ <hr>
33
+
34
+ + 0.4.2 [March 11 2013]
35
+ - Generator moved to a standalone gem - [Enginery](https://github.com/espresso/enginery)
36
+ - helpers are now included via `helper` method - [ab2063461](https://github.com/espresso/espresso/commit/ab2063461)
37
+ - `link_to` helper [db51c839](https://github.com/espresso/espresso/commit/db51c839cf2e1165bceb5d394b3706e53c59f0b4)
38
+ - make index action to serve /index URL [fb763c64](https://github.com/espresso/espresso/commit/fb763c644092577627321a0d672e3cc060f9c9cf)
39
+ - Added `reject_automount!` for controllers that should not be mounted at automount [f5ce4723a](https://github.com/espresso/espresso/commit/f5ce4723a)
40
+ - Fixed RDoc generation on Ruby 2.0.0 - [0ad4bbe951](https://github.com/espresso/espresso/commit/0ad4bbe951)
41
+ - trap INT and TERM signals to gracefully stop web server - [fcbebf974](https://github.com/espresso/espresso/commit/fcbebf9740a49065b31ad8d65dcc0d31cf80247b)
42
+
43
+ <hr>
44
+
45
+ + 0.4.1 [Feb 18 2013]
46
+ - support for various streaming backends - [bd844acf](https://github.com/espresso/espresso/commit/bd844acf)
47
+ - added transfer_encoding setup - [e6f4805f4](https://github.com/espresso/espresso/commit/e6f4805f478050df9a7a1206e7ed8ae9b94da039)
48
+
49
+ <hr>
50
+
51
+ + 0.4.0 [Feb 11 2013] - First Stable Release
52
+ - Created a handy generator to easily generate projects, controllers, routes etc.
53
+ - Path to templates are now resolved by controller name, not by base URL
54
+ - Verbified actions has priority over verbless ones, regardless defining order
55
+ - Removing Appetite dependency
56
+ - Writing a new router crafted for specific Espresso needs. Also it tends to be faster than Rack::URLMap
57
+ - Rewrite rules can now be defined inside controllers
58
+ - Splitting codebase into `e-core` and `e-more`
59
+ - Moved monkey-patches to e-ext
60
+ - `format` now accepts only formats, not action names.
61
+ - Added `format_for` to define formats for specific action.
62
+ - Added `disable_format_for` to disable formats for specific action.
63
+ - Sprockets support
64
+ - `assets_loader` renamed to `assets_mapper`
65
+ - Added tag helpers like `js_tag`, `css_tag`, `png_tag` etc.
66
+ - Slim engine are now automatically registered without errors
67
+ - Dropped support for inter-controller rendering
68
+ - Added `render_file` method
69
+ - Fixed Crudifier to work well with ActiveRecord models
70
+ - `route` are now RESTful friendly
71
+ - Allow to include actions from modules
72
+ - Accept multiple controllers at mount
73
+ - `invoke` and `fetch` will NOT pass actual params. Only `pass` will do.
74
+ - Considerable code cleanup and refactoring. Special thanks to @mindreframer.
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source 'http://rubygems.org'
2
+ gemspec
3
+ gem 'rake', '~> 10'
4
+ gem 'specular', '>= 0.2.1'
5
+ gem 'sonar', '>= 0.1.6'
6
+ gem 'slim'
7
+ gem 'haml'
8
+ gem 'rabl'
9
+ gem 'json'
10
+ gem 'sass'
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+
2
+ Copyright (c) 2012-2013 Silviu Rusu <slivuz@gmail.com>
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ of this software and associated documentation files (the "Software"),
6
+ to deal in the Software without restriction, including without limitation
7
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
8
+ and/or sell copies of the Software, and to permit persons to whom the Software
9
+ is furnished to do so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in all
12
+ copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,461 @@
1
+
2
+ <a href="http://espresso.github.com/">
3
+ <img src="http://espresso.github.com/images/logo.png" align="right" /></a>
4
+
5
+ <a href="https://travis-ci.org/espresso/espresso">
6
+ <img src="https://travis-ci.org/espresso/espresso.png" ></a>
7
+
8
+ ### [Espresso Framework](http://espresso.github.com)
9
+
10
+ ### Scalable Web Framework aimed at Speed and Simplicity
11
+
12
+ ## Install
13
+
14
+ ```bash
15
+ $ [sudo] gem install e
16
+ ```
17
+
18
+ or update `Gemfile` by adding:
19
+
20
+ ```ruby
21
+ gem 'e'
22
+ ```
23
+
24
+ ## Quick Start
25
+
26
+ **One-file App:**
27
+
28
+ ```ruby
29
+ require 'e' # or Bundler.require
30
+
31
+ class App < E
32
+ map '/'
33
+
34
+ def index
35
+ "Hello Espresso World!"
36
+ end
37
+ end
38
+
39
+ App.run
40
+ ```
41
+
42
+ **Full-fledged application using [Enginery](https://github.com/espresso/enginery)**
43
+
44
+ ```bash
45
+ $ enginery g
46
+ $ ruby app.rb # or rackup
47
+ ```
48
+
49
+ ## Tutorial
50
+
51
+
52
+ ### Intro
53
+
54
+ [Actions](https://github.com/espresso/espresso/blob/master/docs/Intro.md#actions) |
55
+ [Controllers](https://github.com/espresso/espresso/blob/master/docs/Intro.md#controllers) |
56
+ [Slices](https://github.com/espresso/espresso/blob/master/docs/Intro.md#slices) |
57
+ [MVC?](https://github.com/espresso/espresso/blob/master/docs/Intro.md#mvc) |
58
+ [Models?](https://github.com/espresso/espresso/blob/master/docs/Intro.md#models)
59
+
60
+ ### Routing
61
+
62
+ [Base URL](https://github.com/espresso/espresso/blob/master/docs/Routing.md#base-url) |
63
+ [Canonicals](https://github.com/espresso/espresso/blob/master/docs/Routing.md#canonicals) |
64
+ [Actions](https://github.com/espresso/espresso/blob/master/docs/Routing.md#actions) |
65
+ [Action Mapping](https://github.com/espresso/espresso/blob/master/docs/Routing.md#action-mapping) |
66
+ [Action Aliases](https://github.com/espresso/espresso/blob/master/docs/Routing.md#action-aliases) |
67
+ [Shared Actions](https://github.com/espresso/espresso/blob/master/docs/Routing.md#shared-actions)
68
+ <br>
69
+ [Parametrization](https://github.com/espresso/espresso/blob/master/docs/Routing.md#parametrization) |
70
+ [Format](https://github.com/espresso/espresso/blob/master/docs/Routing.md#format) |
71
+ [RESTful Actions](https://github.com/espresso/espresso/blob/master/docs/Routing.md#restful-actions) |
72
+ [Hosts](https://github.com/espresso/espresso/blob/master/docs/Routing.md#hosts) |
73
+ [Rewriter](https://github.com/espresso/espresso/blob/master/docs/Routing.md#rewriter)
74
+
75
+
76
+ ### Setup
77
+
78
+ [Global Setup](https://github.com/espresso/espresso/blob/master/docs/Setup.md#global-setup) |
79
+ [Setup by Name](https://github.com/espresso/espresso/blob/master/docs/Setup.md#setup-by-name) |
80
+ [Setup by Format](https://github.com/espresso/espresso/blob/master/docs/Setup.md#setup-by-format) |
81
+ [Remote Setup](https://github.com/espresso/espresso/blob/master/docs/Setup.md#remote-setup)
82
+
83
+ ### Workflow
84
+
85
+ [Route](https://github.com/espresso/espresso/blob/master/docs/Workflow.md#route) |
86
+ [Params](https://github.com/espresso/espresso/blob/master/docs/Workflow.md#params) |
87
+ [Passing Control](https://github.com/espresso/espresso/blob/master/docs/Workflow.md#passing-control) |
88
+ [Fetching Body](https://github.com/espresso/espresso/blob/master/docs/Workflow.md#fetching-body) |
89
+ [Halt](https://github.com/espresso/espresso/blob/master/docs/Workflow.md#halt) |
90
+ [Redirect](https://github.com/espresso/espresso/blob/master/docs/Workflow.md#redirect) |
91
+ [Reload](https://github.com/espresso/espresso/blob/master/docs/Workflow.md#reload) |
92
+ [Error Handlers](https://github.com/espresso/espresso/blob/master/docs/Workflow.md#error-handlers) |
93
+ [Hooks](https://github.com/espresso/espresso/blob/master/docs/Workflow.md#hooks) |
94
+ [Authorization](https://github.com/espresso/espresso/blob/master/docs/Workflow.md#authorization) |
95
+ [Sessions](https://github.com/espresso/espresso/blob/master/docs/Workflow.md#sessions) |
96
+ [Flash](https://github.com/espresso/espresso/blob/master/docs/Workflow.md#flash) |
97
+ [Cookies](https://github.com/espresso/espresso/blob/master/docs/Workflow.md#cookies) |
98
+ [Content Type](https://github.com/espresso/espresso/blob/master/docs/Workflow.md#content-type) |
99
+ [Charset](https://github.com/espresso/espresso/blob/master/docs/Workflow.md#charset) |
100
+ [Cache Control](https://github.com/espresso/espresso/blob/master/docs/Workflow.md#cache-control) |
101
+ [Expires](https://github.com/espresso/espresso/blob/master/docs/Workflow.md#expires) |
102
+ [Last Modified](https://github.com/espresso/espresso/blob/master/docs/Workflow.md#last-modified) |
103
+ [Accepted Content Type](https://github.com/espresso/espresso/blob/master/docs/Workflow.md#accepted-content-type) |
104
+ [Send File](https://github.com/espresso/espresso/blob/master/docs/Workflow.md#send-file) |
105
+ [Send Files](https://github.com/espresso/espresso/blob/master/docs/Workflow.md#send-files) |
106
+ [Attachment](https://github.com/espresso/espresso/blob/master/docs/Workflow.md#attachment) |
107
+ [Headers](https://github.com/espresso/espresso/blob/master/docs/Workflow.md#headers) |
108
+ [Helpers](https://github.com/espresso/espresso/blob/master/docs/Workflow.md#helpers) |
109
+
110
+
111
+ ### View API
112
+
113
+ [Engine](https://github.com/espresso/espresso/blob/master/docs/ViewAPI.md#engine) |
114
+ [Extension](https://github.com/espresso/espresso/blob/master/docs/ViewAPI.md#extension) |
115
+ [Templates Path](https://github.com/espresso/espresso/blob/master/docs/ViewAPI.md#templates-path) |
116
+ [Layouts Path](https://github.com/espresso/espresso/blob/master/docs/ViewAPI.md#layouts-path) |
117
+ [Layout](https://github.com/espresso/espresso/blob/master/docs/ViewAPI.md#layout)
118
+ <br>
119
+ [Rendering Templates](https://github.com/espresso/espresso/blob/master/docs/ViewAPI.md#rendering-templates) |
120
+ [Rendering Layouts](https://github.com/espresso/espresso/blob/master/docs/ViewAPI.md#rendering-layouts) |
121
+ [Ad hoc Rendering](https://github.com/espresso/espresso/blob/master/docs/ViewAPI.md#ad-hoc-rendering) |
122
+ [Path Resolver](https://github.com/espresso/espresso/blob/master/docs/ViewAPI.md#path-resolver) |
123
+ [Templates Compilation](https://github.com/espresso/espresso/blob/master/docs/ViewAPI.md#templates-compilation)
124
+
125
+ ### Streaming
126
+
127
+ [Server-Sent Events](https://github.com/espresso/espresso/blob/master/docs/Streaming.md#server-sent-events) |
128
+ [WebSockets](https://github.com/espresso/espresso/blob/master/docs/Streaming.md#websockets) |
129
+ [Chunked Responses](https://github.com/espresso/espresso/blob/master/docs/Streaming.md#chunked-responses)
130
+
131
+
132
+ ### Espresso Lungo
133
+
134
+ Extending Espresso functionality via [`Espresso Lungo`](https://github.com/espresso/espresso-lungo#espresso-lungo) gem:
135
+
136
+ Install:
137
+ ```bash
138
+ $ gem install el
139
+ ```
140
+
141
+ Load:
142
+ ```ruby
143
+ require 'el'
144
+ ```
145
+
146
+ Or simply add `gem 'el'` to Gemfile.
147
+
148
+ Functionality added by `Espresso Lungo`:
149
+
150
+ <a href="https://github.com/espresso/espresso-lungo/blob/master/docs/CRUD.md" target="_blank">
151
+ CRUD</a> |
152
+ <a href="https://github.com/espresso/espresso-lungo/blob/master/docs/Assets.md" target="_blank">
153
+ Assets</a> |
154
+ <a href="https://github.com/espresso/espresso-lungo/blob/master/docs/ContentHelpers.md" target="_blank">
155
+ Content Helpers</a> |
156
+ <a href="https://github.com/espresso/espresso-lungo/blob/master/docs/TagFactory.md" target="_blank">
157
+ Tag Factory</a> |
158
+ <a href="https://github.com/espresso/espresso-lungo/blob/master/docs/CacheManager.md" target="_blank">
159
+ Cache Manager</a>
160
+
161
+
162
+ ### Deploy
163
+
164
+ [Controllers](https://github.com/espresso/espresso/blob/master/docs/Deploy.md#controllers) |
165
+ [Slices](https://github.com/espresso/espresso/blob/master/docs/Deploy.md#slices) |
166
+ [Roots](https://github.com/espresso/espresso/blob/master/docs/Deploy.md#roots) |
167
+ [Arbitrary Applications](https://github.com/espresso/espresso/blob/master/docs/Deploy.md#arbitrary-applications) |
168
+ [Run](https://github.com/espresso/espresso/blob/master/docs/Deploy.md#run) |
169
+ [config.ru](https://github.com/espresso/espresso/blob/master/docs/Deploy.md#configru)
170
+
171
+
172
+ <hr/>
173
+
174
+ # Highlights / Motivation
175
+
176
+
177
+ Performance
178
+ ---
179
+
180
+ In terms of performance, the only really important thing for any framework it is to add as low overhead as possible.
181
+
182
+ The overhead are the time consumed by framework to accept the request then prepare and send response.
183
+
184
+ The tests that follows will allow to disclose the overhead added by various frameworks.
185
+
186
+ The overhead are calculated by dividing 1000 milliseconds to **framework’s standard speed**.
187
+
188
+ The **framework’s standard speed** are the speed of a "HelloWorld" app running on top of given framework.
189
+
190
+ The **framework’s standard speed** means nothing by itself. It is only used to calculate the framework’s overhead.
191
+
192
+ Tested apps will run on `Thin` web server and will return a trivial "Hello World!" response.
193
+
194
+ Hardware used:
195
+
196
+ Processor Name: Intel Core i5
197
+ Processor Speed: 3.31 GHz
198
+ Number of Processors: 1
199
+ Total Number of Cores: 4
200
+ Memory: 8 GB
201
+
202
+ To run tests on your hardware, clone Espresso Framework repository and execute `rake overhead` inside it.
203
+
204
+ Test results:
205
+
206
+ ---
207
+ Speed Overhead 1ms-app 5ms-app 10ms-app 20ms-app 50ms-app 100ms-app
208
+ espresso 5518 0.18ms 847 193 98 49 19 9
209
+ sinatra 3629 0.28ms 783 189 97 49 19 9
210
+ rails 792 1.26ms 442 159 88 47 19 9
211
+ ---
212
+
213
+ **1ms-app** shows your app speed when your actions takes **1ms** to run.<br>
214
+ **10ms-app** shows your app speed when your actions takes **10ms** to run.<br>
215
+ etc.
216
+
217
+ The app speed are calculated as follow:
218
+
219
+ 1000 / (time taken by action + time taken by framework)
220
+
221
+ So, if your actions takes about 1ms and you use a framework with overhead of 0.18ms, the app speed will be:
222
+
223
+ 1000 / ( 1 + 0.18 ) = 847 requests per second
224
+
225
+ However, if framework's overhead is of **1ms** or more, the app speed will decrease dramatically:
226
+
227
+ 1000 / ( 1 + 1.26 ) = 442 requests per second
228
+
229
+
230
+ **Conclusions?**
231
+
232
+ The framework speed matter only if your code matter.
233
+
234
+ If you develop a site aimed to serve a serious amount of requests,
235
+ you should write actions that takes insignificant amount of time.
236
+
237
+ Only after that it make sense to think about framework speed.
238
+
239
+ **Worth to Note** - Espresso has built-in [cache manager](https://github.com/espresso/espresso/blob/master/docs/Workflow.md#cache-manager)
240
+ as well as [views compiler](https://github.com/espresso/espresso/blob/master/docs/ViewAPI.md#templates-compilation).
241
+
242
+ These tools may help you to dramatically reduce the time consumed by your actions.
243
+
244
+ Natural Action/Routes/Params
245
+ ---
246
+
247
+ I never understood why should i create actions in some file,
248
+ then open another file and directing requests to created action.<br>
249
+ Even worse! To use params inside action, i have to remember how i named them in another file.
250
+ And when i want to change a param name i have to change it in both files?
251
+
252
+ What about consistency?<br>
253
+
254
+ A good tradeoff would be to use some DSL.
255
+
256
+ ```ruby
257
+ get '/book/:id' do
258
+ params[:id]
259
+ end
260
+ ```
261
+
262
+ Looks much better.
263
+
264
+ But! Strings/Regexps as action names? No, thanks.
265
+
266
+ What if i need to remount a bunch of actions to a new root?
267
+ Say from /news to /headlines? Refactoring? Using vars/constants in names? No, Thanks.
268
+
269
+ How do i setup multiple actions?<br>
270
+ How do i find out the currently running action?
271
+
272
+ What if i do a request like "/book/100/?id=200"? What? Should i use unique param names? No, thanks.
273
+
274
+ etc. etc.
275
+
276
+ And why should i remember so many non-natural stuff?
277
+
278
+ Is not Ruby powerful enough? I guess it is:
279
+
280
+ ```ruby
281
+ def book id
282
+
283
+ end
284
+ ```
285
+
286
+ That's a regular **Ruby method** and it's regular **Espresso action**.<br>
287
+ That's also an Espresso route. Yes, the app will respond to **"/book/100"**<br>
288
+ And of course action params are used naturally, through method arguments(`id` rather than `params[:id]`).
289
+
290
+ All this offered by Ruby for free! Why to reinvent the wheel?
291
+
292
+ Expressive Setup
293
+ ---
294
+
295
+ Usually you do not want to instruct each action about how it should behave.
296
+
297
+ It would take eras to define inside each action what content type should it return or what layout should it render.
298
+
299
+ Instead, you will use few lines of code at class level to write instructions that will be followed by all actions.
300
+
301
+ **Example:** Instruct **all** actions under `App` controller to return JSON Content-Type
302
+
303
+ ```ruby
304
+ class App < E
305
+ content_type '.json'
306
+ # ...
307
+ end
308
+ ```
309
+
310
+ But what if you need to setup only specific actions?
311
+
312
+ Simple! Put your setup, well, inside `setup` block and pass action names as parameters.
313
+
314
+ **Example:** Instruct **only** `rss` and `feed` actions to return XML Content-Type
315
+
316
+ ```ruby
317
+ class App < E
318
+
319
+ setup :rss, :feed do
320
+ content_type :xml
321
+ end
322
+ # ...
323
+ end
324
+ ```
325
+
326
+ Well, what if i need to setup for some 10 actions and another setup for another 20 actions?
327
+ Should i pass 30 arguments to `setup`? I do not want to buy a new keyboard every month...
328
+
329
+ That's simple too. Use regular expressions.
330
+
331
+ Ex: setup **only** news related actions:
332
+
333
+ ```ruby
334
+ class App < E
335
+
336
+ setup /news/ do
337
+ # some setup
338
+ end
339
+ # ...
340
+ end
341
+ ```
342
+
343
+
344
+ Slices
345
+ ---
346
+
347
+ Portability and DRY done right and easy.
348
+
349
+ With Espresso, any controller can be mounted under any app.
350
+
351
+ Even more, any set of controllers - a.k.a. **slices** - can be mounted under any app.
352
+
353
+ To create a slice simply put your controllers under some module.
354
+
355
+ Then you can mount that module under any Espresso app.
356
+
357
+ Even more, when mounting you can easily setup all controllers(or some) at once.
358
+
359
+ And of course when mounting, you can give a mount point.
360
+
361
+ ```ruby
362
+ require 'e'
363
+ require 'e-ext' # needed for `Cms.run` and `Cms.mount` to work
364
+
365
+ module Cms
366
+
367
+ class Articles < E
368
+ # ...
369
+ end
370
+
371
+ class News < E
372
+ # ...
373
+ end
374
+
375
+ class Pages < E
376
+ # ...
377
+ end
378
+ end
379
+
380
+ app = Cms.mount do
381
+ # some setup that will run inside each controller
382
+ end
383
+
384
+ # or
385
+ app = Cms.mount do |ctrl|
386
+ # some setup that will run inside controllers that match `ctrl` param
387
+ end
388
+
389
+ app.run
390
+ ```
391
+
392
+ RESTful Actions
393
+ ---
394
+
395
+ By default, verbless actions will respond to any request type.
396
+
397
+ To make some action to respond only to some request type,
398
+ simply prepend the corresponding verb to the action name.
399
+
400
+ ```ruby
401
+ # will respond to any request type
402
+ def book
403
+ # ...
404
+ end
405
+
406
+ # GET
407
+ def get_book
408
+ # ...
409
+ end
410
+
411
+ # POST
412
+ def post_book
413
+ # ...
414
+ end
415
+
416
+ # PUT
417
+ def put_book
418
+ # ...
419
+ end
420
+
421
+ # etc.
422
+ ```
423
+
424
+
425
+ Flexible Rewriter
426
+ ---
427
+
428
+ With Espresso built-in rewriter you can redirect any requests to new URL.
429
+
430
+ Beside trivial redirects rewriter can also pass the control to an arbitrary controller#action or simply halt the request and send the response.
431
+
432
+
433
+ Views Compiler
434
+ ---
435
+
436
+ For most web sites, most time are spent at templates rendering. When rendering templates, most time are spent at reading and compiling.
437
+
438
+ Espresso allow to easily skip these expensive operations by keeping compiled templates in memory and just render them on consequent requests.
439
+
440
+
441
+ ## Contributing
442
+
443
+ - Fork Espresso repository
444
+ - make your changes
445
+ - submit a pull request
446
+
447
+ <hr>
448
+ <p>
449
+ Issues/Bugs:
450
+ <a href="https://github.com/espresso/espresso/issues">
451
+ github.com/espresso/espresso/issues</a>
452
+ </p>
453
+ <p>
454
+ Mailing List: <a href="https://groups.google.com/forum/?fromgroups#!forum/espresso-framework">
455
+ groups.google.com/.../espresso-framework</a>
456
+ </p>
457
+ <p>
458
+ IRC channel: #espressorb on irc.freenode.net
459
+ </p>
460
+
461
+ ### Author - [Silviu Rusu](https://github.com/slivu). License - [MIT](https://github.com/espresso/espresso/blob/master/LICENSE).