roda 2.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG +26 -0
- data/README.rdoc +83 -22
- data/Rakefile +1 -1
- data/doc/release_notes/2.1.0.txt +124 -0
- data/lib/roda/plugins/assets.rb +17 -9
- data/lib/roda/plugins/class_level_routing.rb +5 -2
- data/lib/roda/plugins/delegate.rb +6 -3
- data/lib/roda/plugins/indifferent_params.rb +7 -0
- data/lib/roda/plugins/mailer.rb +18 -1
- data/lib/roda/plugins/multi_route.rb +2 -1
- data/lib/roda/plugins/path.rb +75 -6
- data/lib/roda/plugins/render.rb +33 -14
- data/lib/roda/plugins/static.rb +35 -0
- data/lib/roda/plugins/view_options.rb +161 -0
- data/lib/roda/plugins/view_subdirs.rb +6 -63
- data/lib/roda/version.rb +1 -1
- data/spec/composition_spec.rb +12 -0
- data/spec/matchers_spec.rb +34 -0
- data/spec/plugin/assets_spec.rb +112 -17
- data/spec/plugin/delete_empty_headers_spec.rb +12 -0
- data/spec/plugin/mailer_spec.rb +46 -3
- data/spec/plugin/module_include_spec.rb +17 -0
- data/spec/plugin/multi_route_spec.rb +10 -0
- data/spec/plugin/named_templates_spec.rb +6 -0
- data/spec/plugin/not_found_spec.rb +1 -1
- data/spec/plugin/path_spec.rb +76 -0
- data/spec/plugin/render_each_spec.rb +6 -0
- data/spec/plugin/render_spec.rb +40 -1
- data/spec/plugin/sinatra_helpers_spec.rb +5 -0
- data/spec/plugin/static_spec.rb +30 -0
- data/spec/plugin/view_options_spec.rb +117 -0
- data/spec/spec_helper.rb +5 -1
- data/spec/views/multiple-layout.erb +1 -0
- data/spec/views/multiple.erb +1 -0
- metadata +10 -4
- data/spec/plugin/static_path_info_spec.rb +0 -56
- data/spec/plugin/view_subdirs_spec.rb +0 -44
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3c4531548815188387cfc8a1cd6eb4803ca52228
|
4
|
+
data.tar.gz: f25f081bd7ed74c63d5b4da6ca87d8ad3a413c42
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4fd832236f0c0a59129f10303c56c82f3ec9e63d27f8c85cd5080e0ac1cd3477cd3321f309618a6c2d4690b43b79ab5d687c9243957156d61532e472118943a1
|
7
|
+
data.tar.gz: ca178d1d5b1945ad3f94a9d4273d9cbbfd8726f5f5f924d7eefd9949d0be732eb028e6f2fd1f7f2e7eee526ae04ef796bb2899ebbcbb690bac4a13e0021241af
|
data/CHANGELOG
CHANGED
@@ -1,3 +1,29 @@
|
|
1
|
+
= 2.1.0 (2015-03-13)
|
2
|
+
|
3
|
+
* Have add_file in the mailer plugin support blocks, which are called after the file has been added (jeremyevans)
|
4
|
+
|
5
|
+
* Add append_view_subdir to view_options, for appending to an existing view subdirectory (jeremyevans)
|
6
|
+
|
7
|
+
* Rename view_subdirs plugin to view_options, add support for branch/route specific view/layout options/locals (jeremyevans)
|
8
|
+
|
9
|
+
* Merge :locals set in the render plugin options into :locals provided in call to view/render (jeremyevans)
|
10
|
+
|
11
|
+
* Add support for registering classes in the path plugin for use with Roda#path (jeremyevans)
|
12
|
+
|
13
|
+
* Use :add_script_name app option as default for path method :add_script_name option in path plugin (jeremyevans)
|
14
|
+
|
15
|
+
* Support :add_script_name app option in assets plugin, to prefix URLs with SCRIPT_NAME (jeremyevans)
|
16
|
+
|
17
|
+
* Make r.multi_route in multi_route plugin work without any named routes defined (jeremyevans)
|
18
|
+
|
19
|
+
* Add :static plugin, for more easily serving static files (jeremyevans)
|
20
|
+
|
21
|
+
* Recognize Roda :root option in render and assets plugins (jeremyevans)
|
22
|
+
|
23
|
+
* Make :layout=>false option in render plugin override previous layout template (jeremyevans)
|
24
|
+
|
25
|
+
* Make add_file in the mailer plugin add the files after the email body instead of before (jeremyevans)
|
26
|
+
|
1
27
|
= 2.0.0 (2015-02-13)
|
2
28
|
|
3
29
|
* Allow Roda app to be used as a regular rack app even when using the middleware plugin (jeremyevans)
|
data/README.rdoc
CHANGED
@@ -14,16 +14,39 @@ Bugs :: http://github.com/jeremyevans/roda/issues
|
|
14
14
|
Google Group :: http://groups.google.com/group/ruby-roda
|
15
15
|
IRC :: irc://chat.freenode.net/#roda
|
16
16
|
|
17
|
-
==
|
17
|
+
== Goals
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
19
|
+
* Simplicity
|
20
|
+
* Reliability
|
21
|
+
* Extensibility
|
22
|
+
* Performance
|
23
|
+
|
24
|
+
=== Simplicity
|
25
|
+
|
26
|
+
Roda is designed to be simple, both internally and externally.
|
27
|
+
It uses a routing tree to enable you to write simpler and DRYer
|
28
|
+
code.
|
29
|
+
|
30
|
+
=== Reliability
|
31
|
+
|
32
|
+
Roda is one of the first ruby web frameworks where immutability
|
33
|
+
is supported and encouraged. Roda apps are designed to be frozen
|
34
|
+
in production, which eliminates possible thread safety issues.
|
35
|
+
Additionally, Roda limits the instance variables, constants, and
|
36
|
+
methods that it uses, so that they do not conflict with the ones
|
37
|
+
you use for your application.
|
38
|
+
|
39
|
+
=== Extensibility
|
40
|
+
|
41
|
+
Roda is built completely out of plugins, which makes it very
|
42
|
+
extensible. You can override any part of Roda and call super
|
43
|
+
to get the default behavior.
|
44
|
+
|
45
|
+
=== Performance
|
46
|
+
|
47
|
+
Roda has low per-request overhead, and the use of a routing tree
|
48
|
+
and intelligent caching of internal datastructures makes it one
|
49
|
+
of the fastest ruby web frameworks.
|
27
50
|
|
28
51
|
== Usage
|
29
52
|
|
@@ -43,22 +66,24 @@ Here's a simple application, showing how the routing tree works:
|
|
43
66
|
|
44
67
|
# /hello branch
|
45
68
|
r.on "hello" do
|
69
|
+
# Set variable for all routes in /hello branch
|
70
|
+
@greeting = 'Hello'
|
46
71
|
|
47
72
|
# GET /hello/world request
|
48
73
|
r.get "world" do
|
49
|
-
"
|
74
|
+
"#{@greeting} world!"
|
50
75
|
end
|
51
76
|
|
52
77
|
# /hello request
|
53
78
|
r.is do
|
54
79
|
# GET /hello request
|
55
80
|
r.get do
|
56
|
-
"
|
81
|
+
"#{@greeting}!"
|
57
82
|
end
|
58
83
|
|
59
84
|
# POST /hello request
|
60
85
|
r.post do
|
61
|
-
puts "Someone said
|
86
|
+
puts "Someone said #{@greeting}!"
|
62
87
|
r.redirect
|
63
88
|
end
|
64
89
|
end
|
@@ -588,27 +613,36 @@ The settings are inherited if you happen to subclass +Roda+.
|
|
588
613
|
Roda.opts[:layout] = "guest"
|
589
614
|
|
590
615
|
class Users < Roda; end
|
591
|
-
class Admin < Roda
|
592
|
-
|
593
|
-
|
616
|
+
class Admin < Roda
|
617
|
+
opts[:layout] = "admin"
|
618
|
+
end
|
594
619
|
|
595
620
|
Users.opts[:layout] # => 'guest'
|
596
621
|
Admin.opts[:layout] # => 'admin'
|
597
622
|
|
598
623
|
Feel free to store whatever you find convenient.
|
599
624
|
Note that when subclassing, Roda only does a shallow clone of the settings.
|
625
|
+
|
600
626
|
If you store nested structures and plan to mutate them in subclasses,
|
601
627
|
it is your responsibility to dup the nested structures inside +Roda.inherited+
|
602
|
-
(making sure to call +super+).
|
603
|
-
|
604
|
-
|
605
|
-
Also, note that this means that modifications to the parent class
|
606
|
-
made after subclassing do _not_ affect the subclass.
|
628
|
+
(making sure to call +super+). This should be is done so that that modifications
|
629
|
+
to the parent class made after subclassing do _not_ affect the subclass, and
|
630
|
+
vice-versa.
|
607
631
|
|
608
632
|
The plugins that ship with Roda freeze their settings and only allow modification
|
609
633
|
to their settings by reloading the plugin, and external plugins are encouraged
|
610
634
|
to follow this approach.
|
611
635
|
|
636
|
+
The following options are respected by multiple plugins:
|
637
|
+
|
638
|
+
:add_script_name :: Prepend the SCRIPT_NAME for the request to paths. This is
|
639
|
+
useful if you mount the app as a path under another app.
|
640
|
+
:root :: Set the root path for the app. This defaults to the current working
|
641
|
+
directory of the process.
|
642
|
+
|
643
|
+
There may be other options supported by individual plugins, if so it will be
|
644
|
+
mentioned in the documentation for the plugin.
|
645
|
+
|
612
646
|
== Rendering
|
613
647
|
|
614
648
|
Roda ships with a +render+ plugin that provides helpers for rendering templates.
|
@@ -652,10 +686,10 @@ You can override the default rendering options by passing a hash to the plugin:
|
|
652
686
|
class App < Roda
|
653
687
|
plugin :render,
|
654
688
|
:escape => true, # Automatically escape output in erb templates
|
655
|
-
:views => 'admin_views' # Default views directory
|
689
|
+
:views => 'admin_views', # Default views directory
|
656
690
|
:layout_opts => {:template=>'admin_layout',
|
657
691
|
:ext=>'html.erb'}, # Default layout template options
|
658
|
-
:template_opts => {:default_encoding=>'UTF-8'}
|
692
|
+
:template_opts => {:default_encoding=>'UTF-8'} # Default template options
|
659
693
|
end
|
660
694
|
|
661
695
|
== Sessions
|
@@ -791,6 +825,33 @@ to avoid polluting the scope. Finally, do not add any constants inside
|
|
791
825
|
the InstanceMethods module, add constants to the plugin module itself
|
792
826
|
(+Markdown+ in the above example).
|
793
827
|
|
828
|
+
If you are planning on shipping your plugin in an external gem, it is recommended that you follow
|
829
|
+
{standard gem naming conventions for extensions}[http://guides.rubygems.org/name-your-gem/].
|
830
|
+
So if your plugin module is named +FooBar+, your gem name should be <tt>roda-foo_bar</tt>.
|
831
|
+
|
832
|
+
== No Introspection
|
833
|
+
|
834
|
+
Because a routing tree does not store the routes in a data structure, but
|
835
|
+
directly executes the routing tree block, you cannot introspect the routes
|
836
|
+
when using a routing tree.
|
837
|
+
|
838
|
+
If you would like to introspect your routes when using Roda, there is an
|
839
|
+
external plugin named {roda-route_list}[https://github.com/jeremyevans/roda-route_list],
|
840
|
+
which allows you to add appropriate comments to your routing files, and
|
841
|
+
has a parser that will parse those comments into routing metadata that
|
842
|
+
you can then introspect.
|
843
|
+
|
844
|
+
== Inspiration
|
845
|
+
|
846
|
+
Roda was inspired by {Sinatra}[http://www.sinatrarb.com] and {Cuba}[http://cuba.is],
|
847
|
+
two other Ruby web frameworks.
|
848
|
+
It started out as a fork of Cuba, from which it borrows the idea of using a routing tree
|
849
|
+
(which Cuba in turn took from {Rum}[https://github.com/chneukirchen/rum]).
|
850
|
+
From Sinatra, it takes the ideas that route blocks should return the request bodies
|
851
|
+
and that routes should be canonical.
|
852
|
+
It pilfers the idea for an extensible plugin system from the Ruby database library
|
853
|
+
{Sequel}[http://sequel.jeremyevans.net].
|
854
|
+
|
794
855
|
== License
|
795
856
|
|
796
857
|
MIT
|
data/Rakefile
CHANGED
@@ -0,0 +1,124 @@
|
|
1
|
+
= New Plugins
|
2
|
+
|
3
|
+
* A view_options plugin has been added, for branch/route specific
|
4
|
+
setting of view and layout options and locals. This allows for
|
5
|
+
DRYer code when you want to change the view or layout settings
|
6
|
+
for an entire routing branch. Options and locals set at the
|
7
|
+
branch or route level have higher priority than those set at
|
8
|
+
the plugin level, but lower priority than those provided as
|
9
|
+
arguments to the render/view methods. Example:
|
10
|
+
|
11
|
+
class App < Roda
|
12
|
+
plugin :view_options
|
13
|
+
|
14
|
+
route do |r|
|
15
|
+
r.on 'albums' do
|
16
|
+
layout_options :template=>'layouts/3_columns'
|
17
|
+
layout_locals :heading=>'Albums'
|
18
|
+
view_options :ext=>'haml'
|
19
|
+
view_locals :name=>'Foo'
|
20
|
+
# ...
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
The view_options plugin is also a superset of the previous
|
26
|
+
view_subdirs plugin, and attempts to load view_subdirs will
|
27
|
+
now load view_options. In addition to set_view_subdir, the
|
28
|
+
view_options plugin now supports append_view_subdir, which
|
29
|
+
will append a subdirectory to an existing subdirectory, which
|
30
|
+
makes it simpler to deal with nested view file hierarchies.
|
31
|
+
|
32
|
+
* A static plugin has been added for easily serving static files
|
33
|
+
using Rack::Static. Example:
|
34
|
+
|
35
|
+
class App < Roda
|
36
|
+
plugin :static, ['/js', '/css']
|
37
|
+
# or:
|
38
|
+
plugin :static, ['/js', '/css'], :root=>'pub'
|
39
|
+
end
|
40
|
+
|
41
|
+
= Other New Features
|
42
|
+
|
43
|
+
* Roda now supports a :root option for the application that sets
|
44
|
+
the root directory. This is useful if the application's files
|
45
|
+
are not stored in the process's working directory, which is
|
46
|
+
common for processes containing of multiple Roda applications.
|
47
|
+
|
48
|
+
By setting the :root option, plugins that use the file system
|
49
|
+
will default to making relative paths relative to the :root
|
50
|
+
option instead of the process's working directory. The
|
51
|
+
assets, render, and static plugins currently support the :root
|
52
|
+
option. Example:
|
53
|
+
|
54
|
+
class App < Roda
|
55
|
+
opts[:root] = File.dirname(__FILE__)
|
56
|
+
end
|
57
|
+
|
58
|
+
* Roda now supports an :add_script_name option for the application,
|
59
|
+
which makes plugins automatically prepend the SCRIPT_NAME for the
|
60
|
+
request's environment to any paths created. This allows Roda
|
61
|
+
applications to work transparently whenever they are mounted
|
62
|
+
inside of another rack application.
|
63
|
+
|
64
|
+
The assets and path plugins currently recognize the
|
65
|
+
:add_script_name option. Example:
|
66
|
+
|
67
|
+
class App < Roda
|
68
|
+
opts[:add_script_name] = true
|
69
|
+
end
|
70
|
+
|
71
|
+
* The path plugin now adds a Roda#path method, which creates paths
|
72
|
+
based on the type of argument used. You can register classes
|
73
|
+
with the path plugin by providing Roda.path with a class, which
|
74
|
+
will cause Roda#path to recognize them and handle them accordingly.
|
75
|
+
|
76
|
+
Example:
|
77
|
+
|
78
|
+
class App < Roda
|
79
|
+
plugin :path
|
80
|
+
path(Track){|track| "/albums/#{track.album_id}/tracks/#{track.number}"}
|
81
|
+
|
82
|
+
route do
|
83
|
+
r.get 'tracks/:id' |track_id|
|
84
|
+
r.redirect(path(Track[track_id]))
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
= Other Improvements
|
90
|
+
|
91
|
+
* add_file in the mailer plugin now adds the files after the email
|
92
|
+
body instead of before. This fixes some issues where the email
|
93
|
+
body would end up empty, due to issues with the mail gem's API.
|
94
|
+
|
95
|
+
add_file now accepts a block, and the block is called after the
|
96
|
+
file has been attached. Among other things, this allows you to
|
97
|
+
change the content_type for an attached file:
|
98
|
+
|
99
|
+
add_file 'path/to/file' do
|
100
|
+
response.mail.attachments.last.content_type = 'text/foo'
|
101
|
+
end
|
102
|
+
|
103
|
+
* r.multi_route in the multi_route plugin now works if there are
|
104
|
+
no named routes defined.
|
105
|
+
|
106
|
+
* A render plugin :locals option is now respected, setting defaults
|
107
|
+
to use for locals in views. Additionally, a :locals option in
|
108
|
+
the :layout_opts option is now respected for setting locals in
|
109
|
+
layouts. If both the render plugin option is set and :locals is
|
110
|
+
passed to render/view, the two will be merged together.
|
111
|
+
Previously, providing a :locals option to render/view would cause
|
112
|
+
the plugin level option to be ignored.
|
113
|
+
|
114
|
+
= Backwards Compatibility
|
115
|
+
|
116
|
+
* Using the render plugin :layout=>nil option now removes any
|
117
|
+
layout template set previously using :layout. Previously, the
|
118
|
+
layout template would still be kept, but it would not be used
|
119
|
+
by default.
|
120
|
+
|
121
|
+
* Accessing attachments after adding a file using add_file in the
|
122
|
+
mailer plugin no longer works, as the adding is now delayed until
|
123
|
+
after the body is set. You should now pass a block to add_file
|
124
|
+
if you want to access the attachment after it has been added.
|
data/lib/roda/plugins/assets.rb
CHANGED
@@ -52,6 +52,10 @@ class Roda
|
|
52
52
|
#
|
53
53
|
# <%= assets(:css, :media => 'print') %>
|
54
54
|
#
|
55
|
+
# The assets method will respect the application's :add_script_name option,
|
56
|
+
# if it set it will automatically prefix the path with the SCRIPT_NAME for
|
57
|
+
# the request.
|
58
|
+
#
|
55
59
|
# == Asset Groups
|
56
60
|
#
|
57
61
|
# The asset plugin supports groups for the cases where you have different
|
@@ -209,20 +213,20 @@ class Roda
|
|
209
213
|
# :js_headers :: A hash of additional headers for your rendered javascript files
|
210
214
|
# :js_opts :: Template options to pass to the render plugin (via :template_opts) when rendering javascript assets
|
211
215
|
# :js_route :: Route under :prefix for javascript assets (default: :js_dir)
|
212
|
-
# :path :: Path to your asset source directory (default: 'assets')
|
216
|
+
# :path :: Path to your asset source directory (default: 'assets'). Relative
|
217
|
+
# paths will be considered relative to the application's :root option.
|
213
218
|
# :prefix :: Prefix for assets path in your URL/routes (default: 'assets')
|
214
219
|
# :precompiled :: Path to the compiled asset metadata file. If the file exists, will use compiled
|
215
220
|
# mode using the metadata in the file. If the file does not exist, will use
|
216
221
|
# non-compiled mode, but will write the metadata to the file if compile_assets is called.
|
217
|
-
# :public :: Path to your public folder, in which compiled files are placed (default: 'public')
|
222
|
+
# :public :: Path to your public folder, in which compiled files are placed (default: 'public'). Relative
|
223
|
+
# paths will be considered relative to the application's :root option.
|
218
224
|
module Assets
|
219
225
|
DEFAULTS = {
|
220
226
|
:compiled_name => 'app'.freeze,
|
221
227
|
:js_dir => 'js'.freeze,
|
222
228
|
:css_dir => 'css'.freeze,
|
223
|
-
:path => 'assets'.freeze,
|
224
229
|
:prefix => 'assets'.freeze,
|
225
|
-
:public => 'public'.freeze,
|
226
230
|
:concat_only => false,
|
227
231
|
:compiled => false,
|
228
232
|
:add_suffix => false,
|
@@ -269,6 +273,8 @@ class Roda
|
|
269
273
|
app.opts[:assets][:orig_opts] = opts
|
270
274
|
end
|
271
275
|
opts = app.opts[:assets]
|
276
|
+
opts[:path] = File.expand_path(opts[:path]||"assets", app.opts[:root]).freeze
|
277
|
+
opts[:public] = File.expand_path(opts[:public]||"public", app.opts[:root]).freeze
|
272
278
|
|
273
279
|
# Combine multiple values into a path, ignoring trailing slashes
|
274
280
|
j = lambda do |*v|
|
@@ -465,23 +471,25 @@ class Roda
|
|
465
471
|
end
|
466
472
|
|
467
473
|
if type == :js
|
468
|
-
tag_start = "<script type=\"text/javascript\" #{attrs} src=\"
|
474
|
+
tag_start = "<script type=\"text/javascript\" #{attrs} src=\""
|
469
475
|
tag_end = JS_END
|
470
476
|
else
|
471
|
-
tag_start = "<link rel=\"stylesheet\" #{attrs} href=\"
|
477
|
+
tag_start = "<link rel=\"stylesheet\" #{attrs} href=\""
|
472
478
|
tag_end = CSS_END
|
473
479
|
end
|
474
480
|
|
481
|
+
url_prefix = request.script_name if self.class.opts[:add_script_name]
|
482
|
+
|
475
483
|
# Create a tag for each individual file
|
476
484
|
if compiled = o[:compiled]
|
477
485
|
if dirs && !dirs.empty?
|
478
486
|
key = dirs.join(DOT)
|
479
487
|
ckey = "#{stype}.#{key}"
|
480
488
|
if ukey = compiled[ckey]
|
481
|
-
"#{tag_start}#{o[:"compiled_#{stype}_prefix"]}.#{key}.#{ukey}.#{stype}#{tag_end}"
|
489
|
+
"#{tag_start}#{url_prefix}/#{o[:"compiled_#{stype}_prefix"]}.#{key}.#{ukey}.#{stype}#{tag_end}"
|
482
490
|
end
|
483
491
|
elsif ukey = compiled[stype]
|
484
|
-
"#{tag_start}#{o[:"compiled_#{stype}_prefix"]}.#{ukey}.#{stype}#{tag_end}"
|
492
|
+
"#{tag_start}#{url_prefix}/#{o[:"compiled_#{stype}_prefix"]}.#{ukey}.#{stype}#{tag_end}"
|
485
493
|
end
|
486
494
|
else
|
487
495
|
asset_dir = o[type]
|
@@ -489,7 +497,7 @@ class Roda
|
|
489
497
|
dirs.each{|f| asset_dir = asset_dir[f]}
|
490
498
|
prefix = "#{dirs.join(SLASH)}/" if o[:group_subdirs]
|
491
499
|
end
|
492
|
-
Array(asset_dir).map{|f| "#{tag_start}#{o[:"#{stype}_prefix"]}#{prefix}#{f}#{o[:"#{stype}_suffix"]}#{tag_end}"}.join(NEWLINE)
|
500
|
+
Array(asset_dir).map{|f| "#{tag_start}#{url_prefix}/#{o[:"#{stype}_prefix"]}#{prefix}#{f}#{o[:"#{stype}_suffix"]}#{tag_end}"}.join(NEWLINE)
|
493
501
|
end
|
494
502
|
end
|
495
503
|
|
@@ -24,14 +24,17 @@ class Roda
|
|
24
24
|
#
|
25
25
|
# # /hello request
|
26
26
|
# is "hello" do
|
27
|
+
# # Set variable for both GET and POST requests
|
28
|
+
# @greeting = 'Hello'
|
29
|
+
#
|
27
30
|
# # GET /hello request
|
28
31
|
# request.get do
|
29
|
-
# "
|
32
|
+
# "#{@greeting}!"
|
30
33
|
# end
|
31
34
|
#
|
32
35
|
# # POST /hello request
|
33
36
|
# request.post do
|
34
|
-
# puts "Someone said
|
37
|
+
# puts "Someone said #{@greeting}!"
|
35
38
|
# request.redirect
|
36
39
|
# end
|
37
40
|
# end
|