e 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +6 -0
- data/CHANGELOG.md +74 -0
- data/Gemfile +10 -0
- data/LICENSE +19 -0
- data/README.md +461 -0
- data/Rakefile +58 -0
- data/docs/Deploy.md +296 -0
- data/docs/Intro.md +179 -0
- data/docs/Routing.md +677 -0
- data/docs/Setup.md +286 -0
- data/docs/Streaming.md +139 -0
- data/docs/ViewAPI.md +493 -0
- data/docs/Workflow.md +1240 -0
- data/e.gemspec +25 -0
- data/lib/e-builder.rb +2 -0
- data/lib/e-builder/base.rb +355 -0
- data/lib/e-builder/setup.rb +238 -0
- data/lib/e-core.rb +28 -0
- data/lib/e-core/constants.rb +74 -0
- data/lib/e-core/controller/actions.rb +128 -0
- data/lib/e-core/controller/mounter.rb +339 -0
- data/lib/e-core/controller/setups_reader.rb +95 -0
- data/lib/e-core/controller/setups_writer.rb +347 -0
- data/lib/e-core/e-core.rb +56 -0
- data/lib/e-core/instance/base.rb +199 -0
- data/lib/e-core/instance/cookies.rb +55 -0
- data/lib/e-core/instance/halt.rb +89 -0
- data/lib/e-core/instance/helpers.rb +78 -0
- data/lib/e-core/instance/invoke.rb +127 -0
- data/lib/e-core/instance/redirect.rb +43 -0
- data/lib/e-core/instance/request.rb +66 -0
- data/lib/e-core/instance/response.rb +54 -0
- data/lib/e-core/instance/send_file.rb +44 -0
- data/lib/e-core/instance/session.rb +64 -0
- data/lib/e-core/instance/setup/auth.rb +224 -0
- data/lib/e-core/instance/setup/generic.rb +209 -0
- data/lib/e-core/instance/stream.rb +155 -0
- data/lib/e-core/rewriter.rb +71 -0
- data/lib/e-core/utils.rb +178 -0
- data/lib/e-ext.rb +26 -0
- data/lib/e-more.rb +3 -0
- data/lib/e-more/view.rb +8 -0
- data/lib/e-more/view/base.rb +205 -0
- data/lib/e-more/view/constants.rb +46 -0
- data/lib/e-more/view/e-builder.rb +37 -0
- data/lib/e-more/view/setup.rb +123 -0
- data/lib/e-more/view/utils.rb +19 -0
- data/lib/e-version.rb +6 -0
- data/lib/e-version.rb~ +6 -0
- data/lib/e.rb +4 -0
- data/test/e-core/test__3rd_party_apps.rb +98 -0
- data/test/e-core/test__accept.rb +55 -0
- data/test/e-core/test__action_alias.rb +96 -0
- data/test/e-core/test__action_name.rb +41 -0
- data/test/e-core/test__alias.rb +37 -0
- data/test/e-core/test__app_auth.rb +94 -0
- data/test/e-core/test__app_map.rb +47 -0
- data/test/e-core/test__around.rb +24 -0
- data/test/e-core/test__auth.rb +161 -0
- data/test/e-core/test__automount.rb +29 -0
- data/test/e-core/test__builtin_helpers.rb +35 -0
- data/test/e-core/test__cache_control.rb +62 -0
- data/test/e-core/test__canonical.rb +73 -0
- data/test/e-core/test__charset.rb +59 -0
- data/test/e-core/test__content_type.rb +54 -0
- data/test/e-core/test__cookies.rb +40 -0
- data/test/e-core/test__error.rb +44 -0
- data/test/e-core/test__expires.rb +78 -0
- data/test/e-core/test__file.rb +30 -0
- data/test/e-core/test__files.rb +21 -0
- data/test/e-core/test__format.rb +111 -0
- data/test/e-core/test__halt.rb +50 -0
- data/test/e-core/test__helpers.rb +24 -0
- data/test/e-core/test__host.rb +91 -0
- data/test/e-core/test__import.rb +46 -0
- data/test/e-core/test__invoke.rb +162 -0
- data/test/e-core/test__last_modified.rb +56 -0
- data/test/e-core/test__mount.rb +99 -0
- data/test/e-core/test__params.rb +110 -0
- data/test/e-core/test__path_rules.rb +83 -0
- data/test/e-core/test__redirect.rb +105 -0
- data/test/e-core/test__rest.rb +106 -0
- data/test/e-core/test__rewriter.rb +231 -0
- data/test/e-core/test__router.rb +171 -0
- data/test/e-core/test__session.rb +69 -0
- data/test/e-core/test__setup.rb +83 -0
- data/test/e-core/test__setup_aliases.rb +66 -0
- data/test/e-core/test__subcontrollers.rb +45 -0
- data/test/e-core/test__transfer_encoding.rb +51 -0
- data/test/e-core/test__utils.rb +51 -0
- data/test/e-more/view/custom-templates/layout.erb +5 -0
- data/test/e-more/view/custom-templates/some-file.erb +1 -0
- data/test/e-more/view/custom-templates/some_partial.erb +1 -0
- data/test/e-more/view/templates/adhoc_test/custom_layout.erb +1 -0
- data/test/e-more/view/templates/adhoc_test/index.erb +1 -0
- data/test/e-more/view/templates/adhoc_test/index.html.erb +1 -0
- data/test/e-more/view/templates/adhoc_test/layouts/custom.erb +1 -0
- data/test/e-more/view/templates/adhoc_test/layouts/master.erb +1 -0
- data/test/e-more/view/templates/adhoc_test/layouts/named.erb +1 -0
- data/test/e-more/view/templates/adhoc_test/layouts/slim_layout_file.slim +5 -0
- data/test/e-more/view/templates/adhoc_test/partial.erb +1 -0
- data/test/e-more/view/templates/adhoc_test/partial.html.erb +1 -0
- data/test/e-more/view/templates/adhoc_test/rabl_file.rabl +2 -0
- data/test/e-more/view/templates/adhoc_test/slim_file.slim +1 -0
- data/test/e-more/view/templates/blah.erb +1 -0
- data/test/e-more/view/templates/canonical_test/index.erb +1 -0
- data/test/e-more/view/templates/e_more_test__view__view_prefix/default/index.erb +1 -0
- data/test/e-more/view/templates/e_more_test__view__view_prefix/nested/app/index.erb +1 -0
- data/test/e-more/view/templates/engine_ext_test/blah.xml.str +1 -0
- data/test/e-more/view/templates/engine_ext_test/custom___ext.xhtml +1 -0
- data/test/e-more/view/templates/engine_ext_test/custom___ext.xml.xhtml +1 -0
- data/test/e-more/view/templates/engine_ext_test/slim.html.slm +1 -0
- data/test/e-more/view/templates/engine_ext_test/slim.slm +1 -0
- data/test/e-more/view/templates/engine_test/blah.haml +1 -0
- data/test/e-more/view/templates/engine_test/blah.txt.slim +1 -0
- data/test/e-more/view/templates/engine_test/blah.xml.str +1 -0
- data/test/e-more/view/templates/engine_test/index.haml +1 -0
- data/test/e-more/view/templates/engine_test/index.xml.erb +1 -0
- data/test/e-more/view/templates/format_test/api.json.erb +1 -0
- data/test/e-more/view/templates/format_test/index.erb +1 -0
- data/test/e-more/view/templates/format_test/index.html.erb +1 -0
- data/test/e-more/view/templates/format_test/index.xml.erb +1 -0
- data/test/e-more/view/templates/format_test/string.erb +1 -0
- data/test/e-more/view/templates/format_test/string.str.str +1 -0
- data/test/e-more/view/templates/generic_test/custom___ext.xhtml +1 -0
- data/test/e-more/view/templates/generic_test/custom___ext.xml.xhtml +1 -0
- data/test/e-more/view/templates/generic_test/get_partial.erb +1 -0
- data/test/e-more/view/templates/generic_test/implicit_template_with_custom_context.erb +1 -0
- data/test/e-more/view/templates/generic_test/implicit_template_with_custom_locals.erb +1 -0
- data/test/e-more/view/templates/generic_test/index.erb +1 -0
- data/test/e-more/view/templates/generic_test/some___action.erb +1 -0
- data/test/e-more/view/templates/layout.erb +1 -0
- data/test/e-more/view/templates/layout.haml +2 -0
- data/test/e-more/view/templates/layout.txt.slim +3 -0
- data/test/e-more/view/templates/layout.xml.erb +1 -0
- data/test/e-more/view/templates/layout__custom_context.erb +1 -0
- data/test/e-more/view/templates/layout__custom_locals.erb +1 -0
- data/test/e-more/view/templates/layout__format.erb +1 -0
- data/test/e-more/view/templates/layout__format.html.erb +1 -0
- data/test/e-more/view/templates/layout__format.xml.erb +1 -0
- data/test/e-more/view/templates/layouts/_header.erb +1 -0
- data/test/e-more/view/templates/layouts/base.erb +1 -0
- data/test/e-more/view/templates/path_test/index.erb +1 -0
- data/test/e-more/view/templates/path_test/partial.erb +1 -0
- data/test/e-more/view/templates/rabl_test/index.rabl +1 -0
- data/test/e-more/view/templates/relpath_test/blah.erb +1 -0
- data/test/e-more/view/templates/relpath_test/index.erb +1 -0
- data/test/e-more/view/templates/relpath_test/partial.erb +1 -0
- data/test/e-more/view/templates/render_file.rabl +2 -0
- data/test/e-more/view/templates/render_file.slim +1 -0
- data/test/e-more/view/templates/render_layout_file.slim +5 -0
- data/test/e-more/view/templates/slim_test/index.slim +1 -0
- data/test/e-more/view/test__adhoc_render.rb +144 -0
- data/test/e-more/view/test__engine.rb +55 -0
- data/test/e-more/view/test__engine_ext.rb +56 -0
- data/test/e-more/view/test__format.rb +101 -0
- data/test/e-more/view/test__generic.rb +153 -0
- data/test/e-more/view/test__path.rb +49 -0
- data/test/e-more/view/test__rabl.rb +20 -0
- data/test/e-more/view/test__relpath.rb +71 -0
- data/test/e-more/view/test__render_file.rb +92 -0
- data/test/e-more/view/test__render_layout.rb +126 -0
- data/test/e-more/view/test__slim.rb +20 -0
- data/test/e-more/view/test__view_prefix.rb +76 -0
- data/test/overhead/espresso-app.rb +11 -0
- data/test/overhead/run.rb +56 -0
- data/test/setup.rb +14 -0
- data/test/support/http_spec_helper.rb +56 -0
- metadata +262 -0
data/.travis.yml
ADDED
data/CHANGELOG.md
ADDED
@@ -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
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.
|
data/README.md
ADDED
@@ -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).
|