roda 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +70 -0
  3. data/README.rdoc +261 -302
  4. data/Rakefile +1 -1
  5. data/doc/release_notes/1.2.0.txt +406 -0
  6. data/lib/roda.rb +206 -124
  7. data/lib/roda/plugins/all_verbs.rb +11 -10
  8. data/lib/roda/plugins/assets.rb +5 -5
  9. data/lib/roda/plugins/backtracking_array.rb +12 -5
  10. data/lib/roda/plugins/caching.rb +10 -8
  11. data/lib/roda/plugins/class_level_routing.rb +94 -0
  12. data/lib/roda/plugins/content_for.rb +6 -0
  13. data/lib/roda/plugins/default_headers.rb +4 -11
  14. data/lib/roda/plugins/delay_build.rb +42 -0
  15. data/lib/roda/plugins/delegate.rb +64 -0
  16. data/lib/roda/plugins/drop_body.rb +33 -0
  17. data/lib/roda/plugins/empty_root.rb +48 -0
  18. data/lib/roda/plugins/environments.rb +68 -0
  19. data/lib/roda/plugins/error_email.rb +1 -2
  20. data/lib/roda/plugins/error_handler.rb +1 -1
  21. data/lib/roda/plugins/halt.rb +7 -5
  22. data/lib/roda/plugins/head.rb +4 -2
  23. data/lib/roda/plugins/header_matchers.rb +17 -9
  24. data/lib/roda/plugins/hooks.rb +16 -32
  25. data/lib/roda/plugins/json.rb +4 -10
  26. data/lib/roda/plugins/mailer.rb +233 -0
  27. data/lib/roda/plugins/match_affix.rb +48 -0
  28. data/lib/roda/plugins/multi_route.rb +9 -11
  29. data/lib/roda/plugins/multi_run.rb +81 -0
  30. data/lib/roda/plugins/named_templates.rb +93 -0
  31. data/lib/roda/plugins/not_allowed.rb +43 -48
  32. data/lib/roda/plugins/path.rb +63 -2
  33. data/lib/roda/plugins/render.rb +79 -48
  34. data/lib/roda/plugins/render_each.rb +6 -0
  35. data/lib/roda/plugins/sinatra_helpers.rb +523 -0
  36. data/lib/roda/plugins/slash_path_empty.rb +25 -0
  37. data/lib/roda/plugins/static_path_info.rb +64 -0
  38. data/lib/roda/plugins/streaming.rb +1 -1
  39. data/lib/roda/plugins/view_subdirs.rb +12 -8
  40. data/lib/roda/version.rb +1 -1
  41. data/spec/integration_spec.rb +33 -0
  42. data/spec/plugin/backtracking_array_spec.rb +24 -18
  43. data/spec/plugin/class_level_routing_spec.rb +138 -0
  44. data/spec/plugin/delay_build_spec.rb +23 -0
  45. data/spec/plugin/delegate_spec.rb +20 -0
  46. data/spec/plugin/drop_body_spec.rb +20 -0
  47. data/spec/plugin/empty_root_spec.rb +14 -0
  48. data/spec/plugin/environments_spec.rb +31 -0
  49. data/spec/plugin/h_spec.rb +1 -3
  50. data/spec/plugin/header_matchers_spec.rb +14 -0
  51. data/spec/plugin/hooks_spec.rb +3 -5
  52. data/spec/plugin/mailer_spec.rb +191 -0
  53. data/spec/plugin/match_affix_spec.rb +22 -0
  54. data/spec/plugin/multi_run_spec.rb +31 -0
  55. data/spec/plugin/named_templates_spec.rb +65 -0
  56. data/spec/plugin/path_spec.rb +66 -2
  57. data/spec/plugin/render_spec.rb +46 -1
  58. data/spec/plugin/sinatra_helpers_spec.rb +534 -0
  59. data/spec/plugin/slash_path_empty_spec.rb +22 -0
  60. data/spec/plugin/static_path_info_spec.rb +50 -0
  61. data/spec/request_spec.rb +23 -0
  62. data/spec/response_spec.rb +12 -1
  63. metadata +48 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 75b82517a1e80d73d99ea7d25a8bd543ba958e7c
4
- data.tar.gz: 4bcb31a61b7f2658092fe80fb339a8651b718edd
3
+ metadata.gz: 3d246589728bb46404806737bb7e67819956f167
4
+ data.tar.gz: e57198e8df759bd70039ff42f94d86583c75c2f8
5
5
  SHA512:
6
- metadata.gz: a8d8776bd1e9c282dc6d5df795a790a2272103421125233ffe5f6112c77c99d00f37f364c7879b73eb03aafd2c946e45e123c0e261f3ff7f1b576936a986e1ee
7
- data.tar.gz: f8b85158682a132cd00d2a929532bb466a15c502f94abd54afcdaad35dde2fab96a2e2ff6d5b180b62220a6e0944de5ac824c0c25285bd04a8e8d39f959ad171
6
+ metadata.gz: 3127e9f7b7525780556555366e82b0e9f565216e62dacdd5e3e7a69e3440a47771ddad5472b94f7c09d15cf6acb49c7bcdb54fb1d469f68569eb5cf77e589dca
7
+ data.tar.gz: f6dd7cda1372931ce0bf92934d584e084f8b1b84d5a181ce1b28bcf951983adce7c477e6b4bdabdad9a8f0038cacafa49ba87948b46a38de0ad23b0b1330d86c
data/CHANGELOG CHANGED
@@ -1,3 +1,73 @@
1
+ = 1.2.0 (2014-12-17)
2
+
3
+ * Don't override explicit nil :default_encoding template option in the render plugin (jeremyevans)
4
+
5
+ * Add remaining_path and matched_path request methods (jeremyevans)
6
+
7
+ * Add slash_path_emty plugin, for considering a path of "/" as empty when doing a terminal match (jeremyevans)
8
+
9
+ * Remove def_verb_method request class method (jeremyevans)
10
+
11
+ * Support :add_script_name, :name, :url, and :url_only options when creating named paths in the path plugin (jeremyevans)
12
+
13
+ * Add match_affix plugin, for overriding default prefix/suffix used in match patterns (jeremyevans)
14
+
15
+ * Add empty_root plugin, for making root matcher also match empty string (jeremyevans)
16
+
17
+ * Add roda_class instance methods to RodaRequest and RodaResponse, to DRY up plugin code (jeremyevans)
18
+
19
+ * Add sinatra_helpers plugin, porting Sinatra::Helpers methods not covered by other plugins (jeremyevans)
20
+
21
+ * Don't set the default headers until the response is finished (jeremyevans)
22
+
23
+ * Add RodaRequest#default_redirect_status, so plugins can override the default status used for redirects (jeremyevans)
24
+
25
+ * Add drop_body plugin, for automatically dropping body and Content-{Length,Type} headers based on response status (jeremyevans)
26
+
27
+ * Add clear_middleware! class method, for clearing the current middleware (jeremyevans)
28
+
29
+ * Add inherit_middleware class accessor, allowing users to turn off middleware inheritance (jeremyevans)
30
+
31
+ * Add multi_run plugin, for dispatching to multiple rack applications based on the request path prefix (jeremyevans)
32
+
33
+ * Add environments plugin, for handling development/test/production environments (jeremyevans)
34
+
35
+ * Do not cache templates by default if RACK_ENV is development (jeremyevans)
36
+
37
+ * Add delay_build plugin, to delay building the rack app until Roda.app is called (jeremyevans)
38
+
39
+ * Add :user_agent hash matcher to the header_matchers plugin (jeremyevans)
40
+
41
+ * Fix caching of templates in the render plugin when :opts or :template_class is used (jeremyevans)
42
+
43
+ * Require loading the render plugin again if you want to change the default layout (jeremyevans)
44
+
45
+ * Pass :css_opts and :js_opts as template options (via :opts) instead of render options when rendering (jeremyevans)
46
+
47
+ * Only pass :opts hash to template class during rendering, instead of all render/view options (jeremyevans)
48
+
49
+ * Support :template_class option in the render plugin for overriding template class to use (jeremyevans)
50
+
51
+ * Automatically dup unfrozen Array/Hash opts values when subclassing (jeremyevans)
52
+
53
+ * Add named_templates plugin, for creating inline templates by name, instead of storing them in the file system (jeremyevans)
54
+
55
+ * Support :template option in for render/view to specify template to use, instead of requiring separate argument (jeremyevans)
56
+
57
+ * Add class_level_routing plugin, for a DSL similar to Sinatra (jeremyevans)
58
+
59
+ * Make RodaRequest.consume_pattern not capture pattern by default (jeremyevans)
60
+
61
+ * Add static_path_info plugin, making Roda not modify PATH_INFO or SCRIPT_NAME during routing (jeremyevans)
62
+
63
+ * Use local/instance variable lookups instead of method calls to improve performance (jeremyevans)
64
+
65
+ * Add RodaRequest#session, and have #session delegate to that (jeremyevans)
66
+
67
+ * Add delegate plugin, for easily creating methods that delegate to request or response (jeremyevans)
68
+
69
+ * Add mailer plugin, allowing use of a routing tree for email instead of web responses (jeremyevans)
70
+
1
71
  = 1.1.0 (2014-11-11)
2
72
 
3
73
  * Add assets plugin, for rendering assets on the fly, or compiling them to a single compressed file (cj, jeremyevans) (#5)
@@ -1,6 +1,6 @@
1
1
  = Roda
2
2
 
3
- Roda is a routing tree web framework.
3
+ Roda is a routing tree web framework toolkit.
4
4
 
5
5
  = Installation
6
6
 
@@ -17,10 +17,11 @@ IRC :: irc://chat.freenode.net/#roda
17
17
  == Inspiration
18
18
 
19
19
  Roda was inspired by {Sinatra}[http://www.sinatrarb.com] and {Cuba}[http://cuba.is],
20
- two other Ruby web frameworks. It started out as a fork of Cuba, from which it borrows
21
- the idea of using a routing tree (which Cuba in turn took from
22
- {Rum}[https://github.com/chneukirchen/rum]). From Sinatra it takes the ideas that
23
- route blocks should return the request bodies and that routes should be canonical.
20
+ two other Ruby web frameworks.
21
+ It started out as a fork of Cuba, from which it borrows the idea of using a routing tree
22
+ (which Cuba in turn took from {Rum}[https://github.com/chneukirchen/rum]).
23
+ From Sinatra, it takes the ideas that route blocks should return the request bodies
24
+ and that routes should be canonical.
24
25
  It pilfers the idea for an extensible plugin system from the Ruby database library
25
26
  {Sequel}[http://sequel.jeremyevans.net].
26
27
 
@@ -67,77 +68,77 @@ Here's a simple application, showing how the routing tree works:
67
68
 
68
69
  run App.app
69
70
 
70
- Here's a breakdown of what is going on in the above block:
71
+ Here's a breakdown of what is going on in the block above:
71
72
 
72
- After requiring the library and subclassing Roda, the +use+ method
73
- is called, which loads a rack middleware into the current
74
- application.
73
+ After requiring the library and subclassing Roda, the +use+ method is called.
74
+ This loads a Rack middleware into the current application.
75
75
 
76
- The +route+ block is called whenever a new request comes in,
77
- and it is yielded an instance of a subclass of <tt>Rack::Request</tt>
78
- with some additional methods for matching routes. By
79
- convention, this argument should be named +r+.
76
+ The +route+ block is called whenever a new request comes in.
77
+ It is yielded an instance of a subclass of <tt>Rack::Request</tt>
78
+ with some additional methods for matching routes.
79
+ By convention, this argument should be named +r+.
80
80
 
81
81
  The primary way routes are matched in Roda is by calling
82
- +r.on+, +r.is+, +r.root+, +r.get+, or +r.post+. These methods are
83
- calling the routing methods, and each of them takes a block. The
84
- block is referred to as a match block.
82
+ +r.on+, +r.is+, +r.root+, +r.get+, or +r.post+.
83
+ Each of these "routing methods" takes a "match block".
85
84
 
86
85
  Each routing method takes each of the arguments (called matchers)
87
- given and tries to match them to the current request. If it is
88
- able to match all of the arguments, it yields to the match block,
89
- otherwise the block is skipped and execution continues.
90
-
91
- +r.on+ matches if all of the arguments match.
92
- +r.is+ matches if all of the arguments match, and there are no
93
- further entries in the path after matching.
94
- +r.get+ when called without arguments matches any +GET+ request.
95
- +r.get+ when called with any arguments matches only if the
96
- current request is a +GET+ request and there are no further entries
97
- in the path after matching.
98
- +r.root+ only matches a +GET+ request where the current path is +/+.
99
-
100
- If a routing method matches and control is yielded to the match
101
- block, whenever the match block returns, Roda will return the
102
- rack response array of status, headers, and body, to the caller.
103
-
104
- If the match block returns a string and the response body hasn't
105
- already been written to, the block return value will interpreted
106
- as the body for the response. If none of the routing methods match
107
- and the route block returns a string, it will be interpreted as the
108
- body for the response.
109
-
110
- +r.redirect+ immediately returns the response, allowing for
111
- code such as <tt>r.redirect(path) if some_condition</tt>. If
112
- called without arguments, it redirects to the current path if
113
- the current request method is not +GET+.
114
-
115
- The +.app+ at the end is an optimization, which you can leave
116
- off, but which saves a few methods call for every response.
86
+ that is given and tries to match it to the current request.
87
+ If the method is able to match all of the arguments, it yields to the match block;
88
+ otherwise, the block is skipped and execution continues.
89
+
90
+ - +r.on+ matches if all of the arguments match.
91
+ - +r.is+ matches if all of the arguments match and there are no
92
+ further entries in the path after matching.
93
+ - +r.get+ matches any +GET+ request when called without arguments.
94
+ - +r.get+ (when called with any arguments) matches only if the
95
+ current request is a +GET+ request and there are no further entries
96
+ in the path after matching.
97
+ - +r.root+ only matches a +GET+ request where the current path is +/+.
98
+
99
+ If a routing method matches and control is yielded to the match block,
100
+ whenever the match block returns, Roda will return the Rack response array
101
+ (containing status, headers, and body) to the caller.
102
+
103
+ If the match block returns a string
104
+ and the response body hasn't already been written to,
105
+ the block return value will be interpreted as the body for the response.
106
+ If none of the routing methods match and the route block returns a string,
107
+ it will be interpreted as the body for the response.
108
+
109
+ +r.redirect+ immediately returns the response,
110
+ allowing for code such as <tt>r.redirect(path) if some_condition</tt>.
111
+ If +r.redirect+ is called without arguments
112
+ and the current request method is not +GET+, it redirects to the current path.
113
+
114
+ The +.app+ at the end is an (optional) optimization.
115
+ It saves a few method calls for every response.
117
116
 
118
117
  == The Routing Tree
119
118
 
120
- Roda is called a routing tree web framework because the way most
121
- sites are structured, routing takes the form of a tree based on the
122
- URL structure of the site. In general, +r.on+ is used to split the
123
- tree into different branches, and +r.is+ is finalizes the routing,
124
- where the request is actually handled.
119
+ Roda is called a routing tree web framework because the way most sites are structured,
120
+ routing takes the form of a tree (based on the URL structure of the site).
121
+ In general:
125
122
 
126
- So a simple routing tree may look something like this:
123
+ - +r.on+ is used to split the tree into different branches.
124
+ - +r.is+ finalizes the routing path.
125
+ - +r.get+ and +r.post+ handle specific request methods.
126
+
127
+ So, a simple routing tree might look something like this:
127
128
 
128
129
  r.on "a" do # /a branch
129
130
  r.on "b" do # /a/b branch
130
131
  r.is "c" do # /a/b/c request
131
- r.get do end # GET /a/b/c request
132
+ r.get do end # GET /a/b/c request
132
133
  r.post do end # POST /a/b/c request
133
134
  end
134
- r.get "d" do end # GET /a/b/d request
135
+ r.get "d" do end # GET /a/b/d request
135
136
  r.post "e" do end # POST /a/b/e request
136
137
  end
137
138
  end
138
139
 
139
- It's also possible to handle the same requests, but structure the
140
- routing tree by first branching on the request method:
140
+ It's also possible to handle the same requests,
141
+ but structure the routing tree by first branching on the request method:
141
142
 
142
143
  r.get do # GET
143
144
  r.on "a" do # GET /a branch
@@ -157,42 +158,40 @@ routing tree by first branching on the request method:
157
158
  end
158
159
  end
159
160
 
160
- This allows you to easily separate your +GET+ request handling from
161
- your +POST+ request handling. If you only have a small number of
162
- +POST+ request URLs and a large number of +GET+ request URLs, this
163
- may make things easier.
161
+ This allows you to easily separate your +GET+ request handling
162
+ from your +POST+ request handling.
163
+ If you only have a small number of +POST+ request URLs
164
+ and a large number of +GET+ request URLs, this may make things easier.
164
165
 
165
- However, in general routing first by the path and last by the
166
- request method is likely to lead to simpler and DRYer code. This
167
- is because at any point during the routing, you can act on the
168
- request. For example, if all requests in the +/a+ branch need
169
- need access permission +A+ and all requests in the +/a/b+ branch
170
- need access permission +B+, you can easily handle this in the
171
- routing tree:
166
+ However, routing first by the path and last by the request method
167
+ is likely to lead to simpler and DRYer code.
168
+ This is because you can act on the request at any point during the routing.
169
+ For example, if all requests in the +/a+ branch need access permission +A+
170
+ and all requests in the +/a/b+ branch need access permission +B+,
171
+ you can easily handle this in the routing tree:
172
172
 
173
173
  r.on "a" do # /a branch
174
174
  check_perm(:A)
175
175
  r.on "b" do # /a/b branch
176
176
  check_perm(:B)
177
177
  r.is "c" do # /a/b/c request
178
- r.get do end # GET /a/b/c request
178
+ r.get do end # GET /a/b/c request
179
179
  r.post do end # POST /a/b/c request
180
180
  end
181
- r.get "d" do end # GET /a/b/d request
181
+ r.get "d" do end # GET /a/b/d request
182
182
  r.post "e" do end # POST /a/b/e request
183
183
  end
184
184
  end
185
185
 
186
- Being able to operate on the request at any point during the
187
- the routing is one of the major advantages of Roda compared
188
- to other web frameworks that do not use a routing tree.
186
+ Being able to operate on the request at any point during the routing
187
+ is one of the major advantages of Roda, as compared to frameworks
188
+ that do not use a routing tree.
189
189
 
190
190
  == Matchers
191
191
 
192
- Other than +r.root+, the routing methods all take arguments called
193
- matchers. If all of the matchers match, the routing method yields to
194
- the match block. Here's an example showcasing how different
195
- matchers work:
192
+ Other than +r.root+, the routing methods all take arguments called matchers.
193
+ If all of the matchers match, the routing method yields to the match block.
194
+ Here's an example showcasing how different matchers work:
196
195
 
197
196
  class App < Roda
198
197
  route do |r|
@@ -258,29 +257,28 @@ matchers work:
258
257
  end
259
258
  end
260
259
 
261
- Here's a description of the matchers. Note that segment as used
262
- here means one part of the path preceeded by a +/+. So a path such
263
- as +/foo/bar//baz+ has 4 segments, +/foo+, +/bar+, +/+ and +/baz+.
260
+ Here's a description of the matchers.
261
+ Note that "segment", as used here, means one part of the path preceded by a +/+.
262
+ So, a path such as +/foo/bar//baz+ has four segments: +/foo+, +/bar+, +/+, and +/baz+.
264
263
  The +/+ here is considered the empty segment.
265
264
 
266
265
  === String
267
266
 
268
- If it does not contain a colon or slash, it matches single segment
269
- with the text of the string, preceeded by a slash.
267
+ If a string does not contain a colon or slash, it matches a single segment
268
+ containing the text of the string, preceded by a slash.
270
269
 
271
270
  "" # matches "/"
272
271
  "foo" # matches "/foo"
273
272
  "foo" # does not match "/food"
274
273
 
275
- If it contains any slashes, it matches one additional segment for
276
- each slash:
274
+ If a string contains any slashes, it matches one additional segment for each slash:
277
275
 
278
276
  "foo/bar" # matches "/foo/bar"
279
277
  "foo/bar" # does not match "/foo/bard"
280
278
 
281
- If it contains a colon followed by any <tt>\\w</tt> characters, the colon and
282
- remaing <tt>\\w</tt> characters matches any nonempty segment that contains at
283
- least one character:
279
+ If a string contains a colon followed by any <tt>\\w</tt> characters,
280
+ the colon and remaining <tt>\\w</tt> characters match any nonempty segment
281
+ that contains at least one character:
284
282
 
285
283
  "foo/:id" # matches "/foo/bar", "/foo/baz", etc.
286
284
  "foo/:id" # does not match "/fo/bar"
@@ -295,8 +293,8 @@ You can prefix colons:
295
293
  "foo:x/bar:y" # matches "/food/bard", "/fool/bart", etc.
296
294
  "foo:x/bar:y" # does not match "/foo/bart", "/fool/bar", etc.
297
295
 
298
- If any colons are used, the block will yield one argument for
299
- each segment matched containing the matched text. So:
296
+ If any colons are used, the block will yield one argument
297
+ for each segment matched containing the matched text, so:
300
298
 
301
299
  "foo:x/:y" # matching "/fool/bar" yields "l", "bar"
302
300
 
@@ -304,29 +302,28 @@ Colons that are not followed by a <tt>\\w</tt> character are matched literally:
304
302
 
305
303
  ":/a" # matches "/:/a"
306
304
 
307
- Note that strings are regexp escaped before being used in a regular
308
- expression, so:
305
+ Note that strings must be escaped before being used in a regular expression, so:
309
306
 
310
307
  "\\d+(/\\w+)?" # matches "/\d+(/\w+)?"
311
308
  "\\d+(/\\w+)?" # does not match "/123/abc"
312
309
 
313
310
  === Regexp
314
311
 
315
- Regexps match one or more segments by looking for the pattern preceeded by a
316
- slash:
312
+ Regexps match one or more segments by looking for the pattern,
313
+ preceded by a slash:
317
314
 
318
315
  /foo\w+/ # matches "/foobar"
319
316
  /foo\w+/ # does not match "/foo/bar"
320
317
 
321
- If any patterns are captured by the regexp, they are yielded:
318
+ If any patterns are captured by the Regexp, they are yielded:
322
319
 
323
320
  /foo\w+/ # matches "/foobar", yields nothing
324
321
  /foo(\w+)/ # matches "/foobar", yields "bar"
325
322
 
326
323
  === Symbol
327
324
 
328
- Symbols match any nonempty segment, yielding the segment except for the
329
- preceeding slash:
325
+ Symbols match any nonempty segment,
326
+ yielding the segment except for the preceding slash:
330
327
 
331
328
  :id # matches "/foo" yields "foo"
332
329
  :id # does not match "/"
@@ -338,15 +335,15 @@ Procs match unless they return false or nil:
338
335
  proc{true} # matches anything
339
336
  proc{false} # does not match anything
340
337
 
341
- Procs don't capture anything by default, but they can if you add
342
- the captured text to +r.captures+.
338
+ Procs don't capture anything by default,
339
+ but they can do so if you add the captured text to +r.captures+.
343
340
 
344
341
  === Arrays
345
342
 
346
- Arrays match when any of their elements matches. If multiple matchers
347
- are given to +r.on+, they all must match (an AND condition), while
348
- if an array of matchers is given, only one needs to match (an OR
349
- condition). Evaluation stops at the first matcher that matches.
343
+ Arrays match when any of their elements match.
344
+ If multiple matchers are given to +r.on+, they all must match (an AND condition).
345
+ If an array of matchers is given, only one needs to match (an OR condition).
346
+ Evaluation stops at the first matcher that matches.
350
347
 
351
348
  Additionally, if the matched object is a String, the string is yielded.
352
349
  This makes it easy to handle multiple strings without a Regexp:
@@ -376,7 +373,7 @@ block will be called with the value of the hash.
376
373
 
377
374
  ==== :all
378
375
 
379
- The :all matcher matches if all of the entries in the given array matches. So
376
+ The +:all+ matcher matches if all of the entries in the given array match, so
380
377
 
381
378
  r.on :all=>[:a, :b] do
382
379
  # ...
@@ -388,48 +385,48 @@ is the same as:
388
385
  # ...
389
386
  end
390
387
 
391
- The reason it also exists as a separate hash matcher is so you can use it inside
392
- an array matcher. so:
388
+ The reason it also exists as a separate hash matcher
389
+ is so you can use it inside an array matcher, so:
393
390
 
394
391
  r.on ['foo', {:all=>['foos', :id]}] do
395
392
  end
396
393
 
397
- Would match +/foo+ and +/foos/10+, but not +/foos+.
394
+ would match +/foo+ and +/foos/10+, but not +/foos+.
398
395
 
399
396
  ==== :extension
400
397
 
401
- The :extension matcher matches any nonempty path ending with the given extension:
398
+ The +:extension+ matcher matches any nonempty path ending with the given extension:
402
399
 
403
400
  {:extension => "css"} # matches "/foo.css", "/bar.css"
404
401
  {:extension => "css"} # does not match "/foo.css/x", "/foo.bar", "/.css"
405
402
 
406
- This matcher yields the part before the extension.
403
+ This matcher yields the part found before the period and extension (e.g., +foo+).
407
404
 
408
405
  ==== :method
409
406
 
410
- This matches the method of the request. You can provide an array to specify multiple
411
- request methods and match on any of them:
407
+ The +:method+ matcher matches the method of the request.
408
+ You can provide an array to specify multiple request methods and match on any of them:
412
409
 
413
410
  {:method => :post} # matches POST
414
411
  {:method => ['post', 'patch']} # matches POST and PATCH
415
412
 
416
413
  ==== :param
417
414
 
418
- The :param matcher matches if the given parameter is present, even if empty.
415
+ The +:param+ matcher matches if the given parameter is present (even if it is empty).
419
416
 
420
417
  {:param => "user"} # matches "/foo?user=bar", "/foo?user="
421
418
  {:param => "user"} # does not matches "/foo"
422
419
 
423
420
  ==== :param!
424
421
 
425
- The :param! matcher matches if the given parameter is present and not empty.
422
+ The +:param!+ matcher matches if the given parameter is present and not empty.
426
423
 
427
424
  {:param! => "user"} # matches "/foo?user=bar"
428
425
  {:param! => "user"} # does not matches "/foo", "/foo?user="
429
426
 
430
427
  === false, nil
431
428
 
432
- If false or nil is given directly as a matcher, it doesn't match anything.
429
+ If +false+ or +nil+ is given directly as a matcher, it doesn't match anything.
433
430
 
434
431
  === Everything else
435
432
 
@@ -437,14 +434,15 @@ Everything else matches anything.
437
434
 
438
435
  == Status codes
439
436
 
440
- When it comes time to finalize a response, if a status code has not
441
- been set manually, it will use a 200 status code if anything has been
442
- written to the response, otherwise it will use a 404 status code.
443
- This enables the principle of least surprise to work, where if you
444
- don't handle an action, a 404 response is assumed.
437
+ When it comes time to finalize a response,
438
+ if a status code has not been set manually and anything has been written to the response,
439
+ the response will use a 200 status code.
440
+ Otherwise, it will use a 404 status code.
441
+ This enables the principle of least surprise to work:
442
+ if you don't handle an action, a 404 response is assumed.
445
443
 
446
- You can always set the status code manually via the status attribute
447
- for the response.
444
+ You can always set the status code manually,
445
+ via the +status+ attribute for the response.
448
446
 
449
447
  route do |r|
450
448
  r.get "hello" do
@@ -454,9 +452,10 @@ for the response.
454
452
 
455
453
  == Verb Methods
456
454
 
457
- The main match method is +r.on+, but as displayed above, you can also
458
- use +r.get+ or +r.post+. When called without any arguments, these
459
- match as long as the request has the appropriate method, so:
455
+ The main match method is +r.on+, but as displayed above,
456
+ you can also use +r.get+ or +r.post+.
457
+ When called without any arguments, these match as long
458
+ as the request has the appropriate method, so:
460
459
 
461
460
  r.get do end
462
461
 
@@ -468,7 +467,7 @@ matches any +POST+ request
468
467
 
469
468
  If any arguments are given to the method, these match only
470
469
  if the request method matches, all arguments match, and
471
- only the path has been fully matched by the arguments. So:
470
+ only the path has been fully matched by the arguments, so:
472
471
 
473
472
  r.post "" do end
474
473
 
@@ -478,89 +477,91 @@ matches only +POST+ requests where the current path is +/+.
478
477
 
479
478
  matches only +GET+ requests where the current path is +/a/b+.
480
479
 
481
- The reason for this difference in behavior is that if you are not
482
- providing any arguments, you probably don't want to to also test
483
- for an exact match with the current path. If that is something
484
- you do want, you can provide true as an argument:
480
+ The reason for this difference in behavior is that
481
+ if you are not providing any arguments, you probably don't want
482
+ to also test for an exact match with the current path.
483
+ If that is something you do want, you can provide +true+ as an argument:
485
484
 
486
485
  r.on "foo" do
487
486
  r.get true do # Matches GET /foo, not GET /foo/.*
488
487
  end
489
488
  end
490
489
 
491
- If you want to match the request method and do a partial match
492
- on the request path instead of a full match, you need to use
493
- +r.on+ with the <tt>:method</tt> hash matcher:
490
+ If you want to match the request method
491
+ and do only a partial match on the request path,
492
+ you need to use +r.on+ with the <tt>:method</tt> hash matcher:
494
493
 
495
494
  r.on "foo", :method=>:get do # Matches GET /foo(/.*)?
496
495
  end
497
496
 
498
497
  == Root Method
499
498
 
500
- As displayed above, you can also use +r.root+ as a match method. This
501
- method matches +GET+ requests where the current path +/+. +r.root+ is
502
- similar to <tt>r.get ""</tt>, except that it does not consume the +/+ from the path.
499
+ As displayed above, you can also use +r.root+ as a match method.
500
+ This method matches +GET+ requests where the current path is +/+.
501
+ +r.root+ is similar to <tt>r.get ""</tt>,
502
+ except that it does not consume the +/+ from the path.
503
503
 
504
504
  Unlike the other matching methods, +r.root+ takes no arguments.
505
505
 
506
- Note that +r.root+ does not match if the path is empty, you should use
507
- <tt>r.get true</tt> for that. If you want to match either the
508
- the empty path or +/+, you can use <tt>r.get ["", true]</tt>.
506
+ Note that +r.root+ does not match if the path is empty;
507
+ you should use <tt>r.get true</tt> for that.
508
+ If you want to match either the the empty path or +/+,
509
+ you can use <tt>r.get ["", true]</tt>.
509
510
 
510
- Note that +r.root+ does not match non-GET requests, so to handle
511
- <tt>POST /</tt> requests, use <tt>r.post ''</tt>.
511
+ Note that +r.root+ only matches +GET+ requests.
512
+ So, to handle <tt>POST /</tt> requests, use <tt>r.post ''</tt>.
512
513
 
513
514
  == Request and Response
514
515
 
515
- While the request object is yielded to the route block, it is also
516
- available via the +request+ method. Likewise, the response object
517
- is available via the +response+ method.
516
+ While the request object is yielded to the +route+ block,
517
+ it is also available via the +request+ method.
518
+ Likewise, the response object is available via the +response+ method.
518
519
 
519
- The request object is an instance of a subclass of <tt>Rack::Request</tt>
520
- with some additional methods, and the response object is an
521
- instance of a subclass of <tt>Rack::Response</tt> with some additional
522
- methods.
520
+ The request object is an instance of a subclass of <tt>Rack::Request</tt>,
521
+ with some additional methods.
522
+ The response object is an instance of a subclass of <tt>Rack::Response</tt>,
523
+ with some additional methods.
523
524
 
524
- If you want to extend the request and response objects with additional
525
- modules, you can do so via the +request_module+ or +response_module+
526
- methods, or via plugins.
525
+ If you want to extend the request and response objects with additional modules,
526
+ you can do so via the +request_module+ or +response_module+ methods, or via plugins.
527
527
 
528
528
  == Pollution
529
529
 
530
- Roda tries very hard to avoid polluting the scope of the +route+
531
- block. The only instance variables defined by default in the scope of
532
- the +route+ block are <tt>@_request</tt> and <tt>@_response</tt>. The only methods defined
533
- (beyond the default methods for +Object+) are: +env+, +opts+, +request+,
534
- +response+, +call+, +session+, and +_route+ (private). Constants inside the
535
- Roda namespace are all prefixed with +Roda+ (e.g. <tt>Roda::RodaRequest</tt>). This
536
- should make it unlikely that Roda will cause a namespace issue with your
537
- application code.
530
+ Roda tries very hard to avoid polluting the scope of the +route+ block.
531
+ This should make it unlikely that Roda will cause namespace issues
532
+ with your application code:
533
+
534
+ - The only instance variables defined by default in the scope of the +route+ block
535
+ are <tt>@_request</tt> and <tt>@_response</tt>.
536
+ - The only methods defined (beyond the default methods for +Object+) are:
537
+ +env+, +opts+, +request+, +response+, +call+, +session+, and +_route+ (private).
538
+ - Constants inside the Roda namespace are all prefixed with +Roda+
539
+ (e.g., <tt>Roda::RodaRequest</tt>).
538
540
 
539
541
  == Captures
540
542
 
541
- You may have noticed that some matchers yield a value to the block. The rules
542
- for determining if a matcher will yield a value are simple:
543
+ You may have noticed that some matchers yield a value to the block.
544
+ The rules for determining if a matcher will yield a value are simple:
543
545
 
544
546
  1. Regexp captures: <tt>/posts\/(\d+)-(.*)/</tt> will yield two values, corresponding to each capture.
545
547
  2. String placeholders: <tt>"users/:id"</tt> will yield the value in the position of +:id+.
546
548
  3. Symbols: +:foobar+ will yield if a segment is available.
547
549
  4. File extensions: <tt>:extension=>"css"</tt> will yield the basename of the matched file.
548
- 5. Parameters: <tt>:param=>"user"</tt> will yield the value of the parameter user, if present.
550
+ 5. Parameters: <tt>:param=>"user"</tt> will yield the value of the parameter +user+, if present.
549
551
 
550
- The first case is important because it shows the underlying effect of regex
551
- captures.
552
+ The first case is important because it shows the underlying effect of Regexp captures.
552
553
 
553
- In the second case, the substring +:id+ gets replaced by <tt>([^\\/]+)</tt> and the
554
- regexp becomes <tt>/users\/([^\/]+)/</tt> before performing the match, thus it reverts
555
- to the first form we saw.
554
+ In the second case, the substring +:id+ gets replaced by <tt>([^\\/]+)</tt>
555
+ and the Regexp becomes <tt>/users\/([^\/]+)/</tt> before performing the match.
556
+ Thus, it reverts to the first form we saw.
556
557
 
557
- In the third case, the symbol, no matter what it says, gets replaced
558
- by <tt>/([^\\/]+)/</tt>, and again we are in presence of case 1.
558
+ In the third case, the symbol, no matter what it says,
559
+ gets replaced by <tt>/([^\\/]+)/</tt>, and again we are in presence of case 1.
559
560
 
560
561
  The fourth case, again, reverts to the basic matcher: it generates the string
561
562
  <tt>/([^\/]+?)\.#{ext}\z/</tt> before performing the match.
562
563
 
563
- The fifth case is different: it checks if the the parameter supplied is present
564
+ The fifth case is different: it checks if the parameter supplied is present
564
565
  in the request (via POST or QUERY_STRING) and it pushes the value as a capture.
565
566
 
566
567
  == Composition
@@ -588,19 +589,19 @@ inside a Roda app, using +r.run+:
588
589
 
589
590
  run App.app
590
591
 
591
- This will take any path starting with +/api+ and send it to +API+. In this
592
- example, +API+ is a Roda app, but it could easily be a Sinatra, Rails, or
593
- other Rack app.
592
+ This will take any path starting with +/api+ and send it to +API+.
593
+ In this example, +API+ is a Roda app, but it could easily be
594
+ a Sinatra, Rails, or other Rack app.
594
595
 
595
- When you use +r.run+, Roda calls the given Rack app (+API+ in this
596
- case), and whatever the Rack app returns will be returned as the response
597
- for the current application.
596
+ When you use +r.run+, Roda calls the given Rack app (+API+ in this case);
597
+ whatever the Rack app returns will be returned
598
+ as the response for the current application.
598
599
 
599
600
  === multi_route plugin
600
601
 
601
- If you are just looking to split up the main route block up by branches, you
602
- should use the +multi_route+ plugin, which keeps the current scope of
603
- the route block:
602
+ If you are just looking to split up the main route block up by branches,
603
+ you should use the +multi_route+ plugin,
604
+ which keeps the current scope of the +route+ block:
604
605
 
605
606
  class App < Roda
606
607
  plugin :multi_route
@@ -620,20 +621,20 @@ the route block:
620
621
 
621
622
  run App.app
622
623
 
623
- This allows you to set instance variables in the main route block, and still
624
- have access to them inside the +api+ route block.
624
+ This allows you to set instance variables in the main +route+ block
625
+ and still have access to them inside the +api+ +route+ block.
625
626
 
626
627
  == Testing
627
628
 
628
629
  It is very easy to test Roda with {Rack::Test}[https://github.com/brynary/rack-test]
629
- or {Capybara}[https://github.com/jnicklas/capybara]. Roda's own tests use
630
- {RSpec}[http://rspec.info]. The default rake task will run the specs for Roda, if
631
- RSpec is installed.
630
+ or {Capybara}[https://github.com/jnicklas/capybara].
631
+ Roda's own tests use {RSpec}[http://rspec.info].
632
+ The default Rake task will run the specs for Roda, if RSpec is installed.
632
633
 
633
634
  == Settings
634
635
 
635
- Each Roda app can store settings in the +opts+ hash. The settings are
636
- inherited if you happen to subclass +Roda+.
636
+ Each Roda app can store settings in the +opts+ hash.
637
+ The settings are inherited if you happen to subclass +Roda+.
637
638
 
638
639
  Roda.opts[:layout] = "guest"
639
640
 
@@ -645,26 +646,27 @@ inherited if you happen to subclass +Roda+.
645
646
  Users.opts[:layout] # => 'guest'
646
647
  Admin.opts[:layout] # => 'admin'
647
648
 
648
- Feel free to store whatever you find convenient. Note that when subclassing,
649
- Roda only does a shallow clone of the settings. If you store nested structures
650
- and plan to mutate them in subclasses, it is your responsibility to dup the nested
651
- structures inside +Roda.inherited+ (making sure to call +super+). The
652
- plugins that ship with Roda all handle this. Also, note that this means that
653
- future modifications to the parent class after subclassing do not affect the
654
- subclass.
649
+ Feel free to store whatever you find convenient.
650
+ Note that when subclassing, Roda only does a shallow clone of the settings.
651
+ If you store nested structures and plan to mutate them in subclasses,
652
+ it is your responsibility to dup the nested structures inside +Roda.inherited+
653
+ (making sure to call +super+).
654
+ The plugins that ship with Roda all handle this.
655
+ Also, note that this means that modifications to the parent class
656
+ made after subclassing do _not_ affect the subclass.
655
657
 
656
658
  == Rendering
657
659
 
658
- Roda ships with a +render+ plugin that provides helpers for rendering templates. It uses
659
- {Tilt}[https://github.com/rtomayko/tilt], a gem that interfaces with many template
660
- engines. The +erb+ engine is used by default.
660
+ Roda ships with a +render+ plugin that provides helpers for rendering templates.
661
+ It uses {Tilt}[https://github.com/rtomayko/tilt],
662
+ a gem that interfaces with many template engines.
663
+ The +erb+ engine is used by default.
661
664
 
662
- Note that in order to use this plugin you need to have Tilt installed, along
663
- with the templating engines you want to use.
665
+ Note that in order to use this plugin you need to have Tilt installed,
666
+ along with the templating engines you want to use.
664
667
 
665
668
  This plugin adds the +render+ and +view+ methods, for rendering templates.
666
- The difference between +render+ and +view+ is that +view+ will by default
667
- attempt to render the template inside the default layout template, where
669
+ By default, +view+ will render the template inside the default layout template;
668
670
  +render+ will just render the template.
669
671
 
670
672
  class App < Roda
@@ -674,8 +676,8 @@ attempt to render the template inside the default layout template, where
674
676
  @var = '1'
675
677
 
676
678
  r.is "render" do
677
- # Renders the views/home.erb template, which will have access to the
678
- # instance variable @var, as well as local variable content
679
+ # Renders the views/home.erb template, which will have access to
680
+ # the instance variable @var, as well as local variable content.
679
681
  render("home", :locals=>{:content => "hello, world"})
680
682
  end
681
683
 
@@ -706,9 +708,10 @@ You can override the default rendering options by passing a hash to the plugin:
706
708
 
707
709
  == Sessions
708
710
 
709
- By default, Roda doesn't turn on sessions, but most users are going to
710
- want to turn on session support, and the simplest way to do that is to
711
- use the <tt>Rack::Session::Cookie</tt> middleware that comes with rack:
711
+ By default, Roda doesn't turn on sessions,
712
+ but most users are going to want to turn on session support.
713
+ The simplest way to do this is to use the <tt>Rack::Session::Cookie</tt> middleware
714
+ that comes with Rack:
712
715
 
713
716
  require "roda"
714
717
 
@@ -718,39 +721,39 @@ use the <tt>Rack::Session::Cookie</tt> middleware that comes with rack:
718
721
 
719
722
  == Security
720
723
 
721
- Web application security is a very large topic, but here are some
722
- things you can do with Roda to prevent some common web application
723
- vulnerabilities.
724
+ Web application security is a very large topic,
725
+ but here are some things you can do with Roda
726
+ to prevent some common web application vulnerabilities.
724
727
 
725
728
  === Session Security
726
729
 
727
- If you are using sessions, you should also always set a session
728
- secret using the +:secret+ option as shown above. Make sure this
729
- secret is not disclosed, because if an attacker knows the +:secret+
730
- value, they can inject arbitrary session values, which in the worst case
731
- scenario can lead to remote code execution.
730
+ If you are using sessions, you should also always set a session secret,
731
+ using the +:secret+ option as shown above.
732
+ Make sure that this secret is not disclosed,
733
+ because if an attacker knows the +:secret+ value,
734
+ they can inject arbitrary session values.
735
+ In the worst case scenario, this can lead to remote code execution.
732
736
 
733
- Keep in mind that with <tt>Rack::Session::Cookie</tt>, the content in
734
- the session cookie is not encrypted, just signed to prevent tampering.
735
- This means you should not store any data in the session that itself is
736
- secret.
737
+ Keep in mind that with <tt>Rack::Session::Cookie</tt>,
738
+ the content in the session cookie is not encrypted,
739
+ just signed to prevent tampering.
740
+ This means you should not store any secret data in the session.
737
741
 
738
742
  === Cross Site Request Forgery (CSRF)
739
743
 
740
744
  CSRF can be prevented by using the +csrf+ plugin that ships with Roda,
741
- which uses the {rack_csrf}[https://github.com/baldowl/rack_csrf]
742
- library. Just make sure that you include the CSRF token tags in your
743
- html as appropriate.
745
+ which uses the {rack_csrf}[https://github.com/baldowl/rack_csrf] library.
746
+ Just make sure that you include the CSRF token tags in your HTML, as appropriate.
744
747
 
745
- It's also possible to use the <tt>Rack::Csrf</tt> middleware directly,
748
+ It's also possible to use the <tt>Rack::Csrf</tt> middleware directly;
746
749
  you don't have to use the +csrf+ plugin.
747
750
 
748
751
  === Cross Site Scripting (XSS)
749
752
 
750
753
  The easiest way to prevent XSS with Roda is to use a template library
751
- that automatically escapes output by default. The +:escape+ option
752
- to the render plugin sets the ERB template processor to escape by
753
- default, so that in your templates:
754
+ that automatically escapes output by default.
755
+ The +:escape+ option to the +render+ plugin sets the ERb template processor
756
+ to escape by default, so that in your templates:
754
757
 
755
758
  <%= '<>' %> # outputs &lt;&gt;
756
759
  <%== '<>' %> # outputs <>
@@ -759,10 +762,10 @@ This support requires {Erubis}[http://www.kuwata-lab.com/erubis/].
759
762
 
760
763
  === Other
761
764
 
762
- For prevention of some other vulnerabilities, such as click-jacking,
763
- directory traversal, session hijacking, and IP spoofing, consider using
764
- {Rack::Protection}[https://github.com/rkh/rack-protection], which is
765
- a rack middleware that can be added the usual way:
765
+ For prevention of some other vulnerabilities,
766
+ such as click-jacking, directory traversal, session hijacking, and IP spoofing,
767
+ consider using {Rack::Protection}[https://github.com/rkh/rack-protection].
768
+ This is a Rack middleware that can be added in the usual way:
766
769
 
767
770
  require 'roda'
768
771
  require 'rack/protection'
@@ -773,63 +776,17 @@ a rack middleware that can be added the usual way:
773
776
 
774
777
  == Plugins
775
778
 
776
- Roda provides a way to extend its functionality with plugins. Plugins can
777
- override any Roda method and call +super+ to get the default behavior.
778
-
779
- === Included Plugins
780
-
781
- These plugins ship with roda:
782
-
783
- all_verbs :: Adds routing methods to the request for all http verbs.
784
- assets :: Adds support for rendering CSS/JS javascript assets on the fly
785
- in development, or compiling them into a single compressed file
786
- in production.
787
- backtracking_array :: Allows array matchers to backtrack if later matchers
788
- do not match.
789
- caching :: Adds request and response methods related to http caching.
790
- chunked :: Adds support for streaming template responses using
791
- Transfer-Encoding: chunked.
792
- content_for :: Allows storage of content in one template and retrieval of
793
- that content in a different template.
794
- csrf :: Adds CSRF protection and helper methods using
795
- {rack_csrf}[https://github.com/baldowl/rack_csrf].
796
- default_headers :: Override the default response headers used.
797
- error_email :: Adds an +error_email+ method that can be used to email when
798
- an exception is raised.
799
- error_handler :: Adds a +error+ block that is called for all responses that
800
- raise exceptions.
801
- flash :: Adds a flash handler.
802
- h :: Adds h method for html escaping.
803
- halt :: Augments request#halt method to take status and/or body or status,
804
- headers, and body.
805
- head :: Treat HEAD requests like GET requests with an empty response body.
806
- header_matchers :: Adds host, header, and accept hash matchers.
807
- hooks :: Adds before and after methods to run code before and after requests.
808
- indifferent_params :: Adds params method with indifferent access to params,
809
- allowing use of symbol keys for accessing params.
810
- json :: Allows match blocks to return arrays and hashes, using a json
811
- representation as the response body.
812
- middleware :: Allows the Roda app to be used as a rack middleware, calling the
813
- next middleware if no route matches.
814
- multi_route :: Adds the ability for multiple named route blocks, with the
815
- ability to dispatch to them add any point in the main route block.
816
- not_allowed :: Adds support for automatically returning 405 Method Not Allowed
817
- responses.
818
- not_found :: Adds a +not_found+ block that is called for all 404 responses
819
- without bodies.
820
- pass :: Adds a pass method allowing you to skip the current +r.on+ block as if
821
- it did not match.
822
- path :: Adds support for named paths.
823
- per_thread_caching :: Switches the thread-safe cache from a shared cache to a
824
- per-thread cache.
825
- render :: Adds support for rendering templates via tilt, as described above.
826
- render_each :: Render a template for each value in an enumerable.
827
- streaming :: Adds support for streaming responses.
828
- symbol_matchers :: Adds support for symbol-specific matching regexps.
829
- symbol_views :: Allows match blocks to return template name symbols, uses the
830
- template view as the response body.
831
- view_subdirs :: Allows for setting a view subdirectory to use on a per-request
832
- basis.
779
+ By design, Roda has a very small core, providing only the essentials.
780
+ All nonessential features are added via plugins.
781
+ This is why Roda is referred to as a routing tree web framework toolkit.
782
+ Using a combination of Roda plugins,
783
+ you can build the routing tree web framework that needs your needs.
784
+
785
+ Roda's plugins can override any Roda method and call +super+
786
+ to get the default behavior, which makes Roda very extensible.
787
+
788
+ {Roda ships with a large number of plugins}[http://roda.jeremyevans.net/documentation.html#included-plugins],
789
+ and {some other libraries ship with support for Roda}[http://roda.jeremyevans.net/documentation.html#external].
833
790
 
834
791
  === External Plugins
835
792
 
@@ -841,8 +798,8 @@ autoforme :: Adds support for easily creating a simple administrative front
841
798
 
842
799
  === How to create plugins
843
800
 
844
- Authoring your own plugins is pretty straightforward. Plugins are just modules,
845
- which may contain any of the following modules:
801
+ Authoring your own plugins is pretty straightforward.
802
+ Plugins are just modules, which may contain any of the following modules:
846
803
 
847
804
  InstanceMethods :: module included in the Roda class
848
805
  ClassMethods :: module that extends the Roda class
@@ -851,16 +808,16 @@ RequestClassMethods :: module extending the class of the request
851
808
  ResponseMethods :: module included in the class of the response
852
809
  ResponseClassMethods :: module extending the class of the response
853
810
 
854
- If the plugin responds to +load_dependencies+, it will be called first, and should
855
- be used if the plugin depends on another plugin.
811
+ If the plugin responds to +load_dependencies+, it will be called first,
812
+ and should be used if the plugin depends on another plugin.
856
813
 
857
- If the plugin responds to +configure+, it will be called last, and should be
858
- used to configure the plugin.
814
+ If the plugin responds to +configure+, it will be called last,
815
+ and should be used to configure the plugin.
859
816
 
860
- Both +load_dependencies+ and +configure+ are called with the additional arguments
861
- and block given to the plugin call.
817
+ Both +load_dependencies+ and +configure+ are called
818
+ with the additional arguments and block that was given to the plugin call.
862
819
 
863
- So a simple plugin to add an instance method would be:
820
+ So, a simple plugin to add an instance method would be:
864
821
 
865
822
  module MarkdownHelper
866
823
  module InstanceMethods
@@ -874,14 +831,15 @@ So a simple plugin to add an instance method would be:
874
831
 
875
832
  === Registering plugins
876
833
 
877
- If you want to ship a Roda plugin in a gem, but still have
878
- Roda load it automatically via <tt>Roda.plugin :plugin_name</tt>, you should
879
- place it where it can be required via +roda/plugins/plugin_name+, and
880
- then have the file register it as a plugin via
881
- <tt>Roda::RodaPlugins.register_plugin</tt>. It's recommended but not required
882
- that you store your plugin module in the <tt>Roda::RodaPlugins</tt> namespace:
834
+ If you want to ship a Roda plugin in a gem,
835
+ but still have Roda load it automatically via <tt>Roda.plugin :plugin_name</tt>,
836
+ you should place it where it can be required via +roda/plugins/plugin_name+
837
+ and then have the file register it as a plugin via
838
+ <tt>Roda::RodaPlugins.register_plugin</tt>.
839
+ It's recommended, but not required, that you store your plugin module
840
+ in the <tt>Roda::RodaPlugins</tt> namespace:
883
841
 
884
- module Roda
842
+ class Roda
885
843
  module RodaPlugins
886
844
  module Markdown
887
845
  module InstanceMethods
@@ -895,10 +853,11 @@ that you store your plugin module in the <tt>Roda::RodaPlugins</tt> namespace:
895
853
  end
896
854
  end
897
855
 
898
- You should avoid creating your module directly in the +Roda+ namespace
899
- to avoid polluting the namespace. Additionally, any instance variables
900
- created inside InstanceMethods should be prefixed with an underscore
901
- (e.g. <tt>@_variable</tt>) to avoid polluting the scope.
856
+ To avoid namespace pollution,
857
+ you should avoid creating your module directly in the +Roda+ namespace.
858
+ Additionally, any instance variables created inside +InstanceMethods+
859
+ should be prefixed with an underscore (e.g., <tt>@_variable</tt>)
860
+ to avoid polluting the scope.
902
861
 
903
862
  == License
904
863