roda 2.0.0 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|