roda-cj 0.9.6 → 1.0.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.
- data/CHANGELOG +16 -0
 - data/README.rdoc +211 -103
 - data/Rakefile +1 -1
 - data/doc/release_notes/1.0.0.txt +329 -0
 - data/lib/roda.rb +295 -42
 - data/lib/roda/plugins/all_verbs.rb +1 -1
 - data/lib/roda/plugins/assets.rb +277 -0
 - data/lib/roda/plugins/backtracking_array.rb +1 -1
 - data/lib/roda/plugins/error_email.rb +110 -0
 - data/lib/roda/plugins/multi_route.rb +14 -3
 - data/lib/roda/plugins/not_allowed.rb +10 -3
 - data/lib/roda/plugins/path.rb +38 -0
 - data/lib/roda/plugins/symbol_matchers.rb +1 -1
 - data/lib/roda/plugins/view_subdirs.rb +7 -1
 - data/lib/roda/version.rb +1 -1
 - data/spec/integration_spec.rb +95 -3
 - data/spec/plugin/_erubis_escaping_spec.rb +1 -0
 - data/spec/plugin/assets_spec.rb +86 -0
 - data/spec/plugin/error_email_spec.rb +68 -0
 - data/spec/plugin/multi_route_spec.rb +22 -0
 - data/spec/plugin/not_allowed_spec.rb +13 -0
 - data/spec/plugin/path_spec.rb +29 -0
 - metadata +104 -66
 - checksums.yaml +0 -7
 
    
        data/CHANGELOG
    CHANGED
    
    | 
         @@ -1,5 +1,21 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            = HEAD
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
      
 3 
     | 
    
         
            +
            * Support adding middleware after the route block has been added (jeremyevans)
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            * Allow Roda subclasses to use route block from superclass (jeremyevans)
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            * Have r.multi_route ignore non-String named routes (jeremyevans)
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            * Pick up newly added named routes while running in the multi_route plugin, useful for development (jeremyevans)
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            * Add path plugin, for named path support (jeremyevans) (#4)
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            * Add error_email plugin, for easily emailing an error notification for an exception (jeremyevans)
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
            = 1.0.0 (2014-08-19)
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
            * Don't have :extension hash matcher force a terminal match (jeremyevans)
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
       3 
19 
     | 
    
         
             
            * Add :content option to view method in render plugin to use given content instead of rendering a template (jeremyevans)
         
     | 
| 
       4 
20 
     | 
    
         | 
| 
       5 
21 
     | 
    
         
             
            * Add :escape option to render plugin for using erb templates where <%= %> escapes and <%== %> does not (jeremyevans)
         
     | 
    
        data/README.rdoc
    CHANGED
    
    | 
         @@ -35,25 +35,30 @@ Here's a simple application, showing how the routing tree works: 
     | 
|
| 
       35 
35 
     | 
    
         
             
                use Rack::Session::Cookie, :secret => ENV['SECRET']
         
     | 
| 
       36 
36 
     | 
    
         | 
| 
       37 
37 
     | 
    
         
             
                route do |r|
         
     | 
| 
       38 
     | 
    
         
            -
                  #  
     | 
| 
       39 
     | 
    
         
            -
                  r. 
     | 
| 
      
 38 
     | 
    
         
            +
                  # GET / request
         
     | 
| 
      
 39 
     | 
    
         
            +
                  r.root do
         
     | 
| 
      
 40 
     | 
    
         
            +
                    r.redirect "/hello"
         
     | 
| 
      
 41 
     | 
    
         
            +
                  end
         
     | 
| 
       40 
42 
     | 
    
         | 
| 
       41 
     | 
    
         
            -
             
     | 
| 
       42 
     | 
    
         
            -
             
     | 
| 
       43 
     | 
    
         
            -
                      r.redirect "/hello"
         
     | 
| 
       44 
     | 
    
         
            -
                    end
         
     | 
| 
      
 43 
     | 
    
         
            +
                  # /hello branch
         
     | 
| 
      
 44 
     | 
    
         
            +
                  r.on "hello" do
         
     | 
| 
       45 
45 
     | 
    
         | 
| 
       46 
     | 
    
         
            -
                    #  
     | 
| 
       47 
     | 
    
         
            -
                    r. 
     | 
| 
      
 46 
     | 
    
         
            +
                    # GET /hello/world request
         
     | 
| 
      
 47 
     | 
    
         
            +
                    r.get "world" do
         
     | 
| 
      
 48 
     | 
    
         
            +
                      "Hello world!"
         
     | 
| 
      
 49 
     | 
    
         
            +
                    end
         
     | 
| 
       48 
50 
     | 
    
         | 
| 
       49 
     | 
    
         
            -
             
     | 
| 
       50 
     | 
    
         
            -
             
     | 
| 
       51 
     | 
    
         
            -
             
     | 
| 
      
 51 
     | 
    
         
            +
                    # /hello request
         
     | 
| 
      
 52 
     | 
    
         
            +
                    r.is do
         
     | 
| 
      
 53 
     | 
    
         
            +
                      # GET /hello request
         
     | 
| 
      
 54 
     | 
    
         
            +
                      r.get do
         
     | 
| 
      
 55 
     | 
    
         
            +
                        "Hello!"
         
     | 
| 
       52 
56 
     | 
    
         
             
                      end
         
     | 
| 
       53 
57 
     | 
    
         | 
| 
       54 
     | 
    
         
            -
                      #  
     | 
| 
       55 
     | 
    
         
            -
                      r. 
     | 
| 
       56 
     | 
    
         
            -
                        " 
     | 
| 
      
 58 
     | 
    
         
            +
                      # POST /hello request
         
     | 
| 
      
 59 
     | 
    
         
            +
                      r.post do
         
     | 
| 
      
 60 
     | 
    
         
            +
                        puts "Someone said hello!"
         
     | 
| 
      
 61 
     | 
    
         
            +
                        r.redirect
         
     | 
| 
       57 
62 
     | 
    
         
             
                      end
         
     | 
| 
       58 
63 
     | 
    
         
             
                    end
         
     | 
| 
       59 
64 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -62,8 +67,6 @@ Here's a simple application, showing how the routing tree works: 
     | 
|
| 
       62 
67 
     | 
    
         | 
| 
       63 
68 
     | 
    
         
             
              run App.app
         
     | 
| 
       64 
69 
     | 
    
         | 
| 
       65 
     | 
    
         
            -
            You can now run +rackup+ and enjoy what you have just created.
         
     | 
| 
       66 
     | 
    
         
            -
             
     | 
| 
       67 
70 
     | 
    
         
             
            Here's a breakdown of what is going on in the above block:
         
     | 
| 
       68 
71 
     | 
    
         | 
| 
       69 
72 
     | 
    
         
             
            After requiring the library and subclassing Roda, the +use+ method
         
     | 
| 
         @@ -76,34 +79,120 @@ with some additional methods for matching routes.  By 
     | 
|
| 
       76 
79 
     | 
    
         
             
            convention, this argument should be named +r+.
         
     | 
| 
       77 
80 
     | 
    
         | 
| 
       78 
81 
     | 
    
         
             
            The primary way routes are matched in Roda is by calling
         
     | 
| 
       79 
     | 
    
         
            -
            +r.on+,  
     | 
| 
       80 
     | 
    
         
            -
             
     | 
| 
       81 
     | 
    
         
            -
             
     | 
| 
       82 
     | 
    
         
            -
             
     | 
| 
       83 
     | 
    
         
            -
             
     | 
| 
       84 
     | 
    
         
            -
             
     | 
| 
       85 
     | 
    
         
            -
             
     | 
| 
       86 
     | 
    
         
            -
             
     | 
| 
       87 
     | 
    
         
            -
             
     | 
| 
       88 
     | 
    
         
            -
             
     | 
| 
       89 
     | 
    
         
            -
             
     | 
| 
       90 
     | 
    
         
            -
             
     | 
| 
       91 
     | 
    
         
            -
             
     | 
| 
       92 
     | 
    
         
            -
             
     | 
| 
       93 
     | 
    
         
            -
             
     | 
| 
       94 
     | 
    
         
            -
             
     | 
| 
       95 
     | 
    
         
            -
             
     | 
| 
      
 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.
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
            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.
         
     | 
| 
       96 
109 
     | 
    
         | 
| 
       97 
110 
     | 
    
         
             
            +r.redirect+ immediately returns the response, allowing for
         
     | 
| 
       98 
     | 
    
         
            -
            code such as <tt>r.redirect(path) if some_condition</tt>.
         
     | 
| 
      
 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+.
         
     | 
| 
       99 
114 
     | 
    
         | 
| 
       100 
115 
     | 
    
         
             
            The +.app+ at the end is an optimization, which you can leave
         
     | 
| 
       101 
116 
     | 
    
         
             
            off, but which saves a few methods call for every response.
         
     | 
| 
       102 
117 
     | 
    
         | 
| 
      
 118 
     | 
    
         
            +
            == The Routing Tree
         
     | 
| 
      
 119 
     | 
    
         
            +
             
     | 
| 
      
 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.
         
     | 
| 
      
 125 
     | 
    
         
            +
             
     | 
| 
      
 126 
     | 
    
         
            +
            So a simple routing tree may look something like this:
         
     | 
| 
      
 127 
     | 
    
         
            +
             
     | 
| 
      
 128 
     | 
    
         
            +
              r.on "a" do           # /a branch
         
     | 
| 
      
 129 
     | 
    
         
            +
                r.on "b" do         # /a/b branch
         
     | 
| 
      
 130 
     | 
    
         
            +
                  r.is "c" do       # /a/b/c request
         
     | 
| 
      
 131 
     | 
    
         
            +
                    r.get do end    # GET /a/b/c request
         
     | 
| 
      
 132 
     | 
    
         
            +
                    r.post do end   # POST /a/b/c request
         
     | 
| 
      
 133 
     | 
    
         
            +
                  end
         
     | 
| 
      
 134 
     | 
    
         
            +
                  r.get "d" do end  # GET /a/b/d request
         
     | 
| 
      
 135 
     | 
    
         
            +
                  r.post "e" do end # POST /a/b/e request
         
     | 
| 
      
 136 
     | 
    
         
            +
                end
         
     | 
| 
      
 137 
     | 
    
         
            +
              end
         
     | 
| 
      
 138 
     | 
    
         
            +
             
     | 
| 
      
 139 
     | 
    
         
            +
            It's also possible to handle the same requests, but structure the
         
     | 
| 
      
 140 
     | 
    
         
            +
            routing tree by first branching on the request method:
         
     | 
| 
      
 141 
     | 
    
         
            +
             
     | 
| 
      
 142 
     | 
    
         
            +
              r.get do              # GET 
         
     | 
| 
      
 143 
     | 
    
         
            +
                r.on "a" do         # GET /a branch
         
     | 
| 
      
 144 
     | 
    
         
            +
                  r.on "b" do       # GET /a/b branch
         
     | 
| 
      
 145 
     | 
    
         
            +
                    r.is "c" do end # GET /a/b/c request
         
     | 
| 
      
 146 
     | 
    
         
            +
                    r.is "d" do end # GET /a/b/d request
         
     | 
| 
      
 147 
     | 
    
         
            +
                  end
         
     | 
| 
      
 148 
     | 
    
         
            +
                end
         
     | 
| 
      
 149 
     | 
    
         
            +
              end
         
     | 
| 
      
 150 
     | 
    
         
            +
             
     | 
| 
      
 151 
     | 
    
         
            +
              r.post do             # POST
         
     | 
| 
      
 152 
     | 
    
         
            +
                r.on "a" do         # POST /a branch
         
     | 
| 
      
 153 
     | 
    
         
            +
                  r.on "b" do       # POST /a/b branch
         
     | 
| 
      
 154 
     | 
    
         
            +
                    r.is "c" do end # POST /a/b/c request
         
     | 
| 
      
 155 
     | 
    
         
            +
                    r.is "e" do end # POST /a/b/e request
         
     | 
| 
      
 156 
     | 
    
         
            +
                  end
         
     | 
| 
      
 157 
     | 
    
         
            +
                end
         
     | 
| 
      
 158 
     | 
    
         
            +
              end
         
     | 
| 
      
 159 
     | 
    
         
            +
             
     | 
| 
      
 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.
         
     | 
| 
      
 164 
     | 
    
         
            +
             
     | 
| 
      
 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:
         
     | 
| 
      
 172 
     | 
    
         
            +
             
     | 
| 
      
 173 
     | 
    
         
            +
              r.on "a" do           # /a branch
         
     | 
| 
      
 174 
     | 
    
         
            +
                check_perm(:A)  
         
     | 
| 
      
 175 
     | 
    
         
            +
                r.on "b" do         # /a/b branch
         
     | 
| 
      
 176 
     | 
    
         
            +
                  check_perm(:B)  
         
     | 
| 
      
 177 
     | 
    
         
            +
                  r.is "c" do       # /a/b/c request
         
     | 
| 
      
 178 
     | 
    
         
            +
                    r.get do end    # GET /a/b/c request
         
     | 
| 
      
 179 
     | 
    
         
            +
                    r.post do end   # POST /a/b/c request
         
     | 
| 
      
 180 
     | 
    
         
            +
                  end
         
     | 
| 
      
 181 
     | 
    
         
            +
                  r.get "d" do end  # GET /a/b/d request
         
     | 
| 
      
 182 
     | 
    
         
            +
                  r.post "e" do end # POST /a/b/e request
         
     | 
| 
      
 183 
     | 
    
         
            +
                end
         
     | 
| 
      
 184 
     | 
    
         
            +
              end
         
     | 
| 
      
 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.
         
     | 
| 
      
 189 
     | 
    
         
            +
             
     | 
| 
       103 
190 
     | 
    
         
             
            == Matchers
         
     | 
| 
       104 
191 
     | 
    
         | 
| 
       105 
     | 
    
         
            -
             
     | 
| 
       106 
     | 
    
         
            -
             
     | 
| 
      
 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:
         
     | 
| 
       107 
196 
     | 
    
         | 
| 
       108 
197 
     | 
    
         
             
              class App < Roda
         
     | 
| 
       109 
198 
     | 
    
         
             
                route do |r|
         
     | 
| 
         @@ -136,7 +225,6 @@ are arguments passed to +r.on+. 
     | 
|
| 
       136 
225 
     | 
    
         | 
| 
       137 
226 
     | 
    
         
             
                      # /username/foobar/posts
         
     | 
| 
       138 
227 
     | 
    
         
             
                      r.is "posts" do
         
     | 
| 
       139 
     | 
    
         
            -
             
     | 
| 
       140 
228 
     | 
    
         
             
                        # You can access user here, because the blocks are closures.
         
     | 
| 
       141 
229 
     | 
    
         
             
                        "Total Posts: #{user.posts.size}" #=> "Total Posts: 6"
         
     | 
| 
       142 
230 
     | 
    
         
             
                      end
         
     | 
| 
         @@ -158,7 +246,7 @@ are arguments passed to +r.on+. 
     | 
|
| 
       158 
246 
     | 
    
         
             
                    r.is "login" do
         
     | 
| 
       159 
247 
     | 
    
         | 
| 
       160 
248 
     | 
    
         
             
                      # POST /login, user: foo, pass: baz
         
     | 
| 
       161 
     | 
    
         
            -
                      r.on 
     | 
| 
      
 249 
     | 
    
         
            +
                      r.on({:param=>"user"}, {:param=>"pass"}) do |user, pass|
         
     | 
| 
       162 
250 
     | 
    
         
             
                        "#{user}:#{pass}" #=> "foo:baz"
         
     | 
| 
       163 
251 
     | 
    
         
             
                      end
         
     | 
| 
       164 
252 
     | 
    
         | 
| 
         @@ -180,75 +268,75 @@ The +/+ here is considered the empty segment. 
     | 
|
| 
       180 
268 
     | 
    
         
             
            If it does not contain a colon or slash, it matches single segment
         
     | 
| 
       181 
269 
     | 
    
         
             
            with the text of the string, preceeded by a slash.
         
     | 
| 
       182 
270 
     | 
    
         | 
| 
       183 
     | 
    
         
            -
              "" matches "/"
         
     | 
| 
       184 
     | 
    
         
            -
              "foo" matches "/foo"
         
     | 
| 
       185 
     | 
    
         
            -
              "foo" does not match "/food"
         
     | 
| 
      
 271 
     | 
    
         
            +
              ""    # matches "/"
         
     | 
| 
      
 272 
     | 
    
         
            +
              "foo" # matches "/foo"
         
     | 
| 
      
 273 
     | 
    
         
            +
              "foo" # does not match "/food"
         
     | 
| 
       186 
274 
     | 
    
         | 
| 
       187 
275 
     | 
    
         
             
            If it contains any slashes, it matches one additional segment for
         
     | 
| 
       188 
276 
     | 
    
         
             
            each slash:
         
     | 
| 
       189 
277 
     | 
    
         | 
| 
       190 
     | 
    
         
            -
              "foo/bar" matches "/foo/bar"
         
     | 
| 
       191 
     | 
    
         
            -
              "foo/bar" does not match "/foo/bard"
         
     | 
| 
      
 278 
     | 
    
         
            +
              "foo/bar" # matches "/foo/bar"
         
     | 
| 
      
 279 
     | 
    
         
            +
              "foo/bar" # does not match "/foo/bard"
         
     | 
| 
       192 
280 
     | 
    
         | 
| 
       193 
281 
     | 
    
         
             
            If it contains a colon followed by any <tt>\\w</tt> characters, the colon and
         
     | 
| 
       194 
282 
     | 
    
         
             
            remaing <tt>\\w</tt> characters matches any nonempty segment that contains at
         
     | 
| 
       195 
283 
     | 
    
         
             
            least one character:
         
     | 
| 
       196 
284 
     | 
    
         | 
| 
       197 
     | 
    
         
            -
              "foo/:id" matches "/foo/bar", "/foo/baz", etc.
         
     | 
| 
       198 
     | 
    
         
            -
              "foo/:id" does not match "/fo/bar"
         
     | 
| 
      
 285 
     | 
    
         
            +
              "foo/:id" # matches "/foo/bar", "/foo/baz", etc.
         
     | 
| 
      
 286 
     | 
    
         
            +
              "foo/:id" # does not match "/fo/bar"
         
     | 
| 
       199 
287 
     | 
    
         | 
| 
       200 
288 
     | 
    
         
             
            You can use multiple colons in a string:
         
     | 
| 
       201 
289 
     | 
    
         | 
| 
       202 
     | 
    
         
            -
              ":x/:y" matches "/foo/bar", "/bar/foo" etc.
         
     | 
| 
       203 
     | 
    
         
            -
              ":x/:y" does not match "/foo", "/bar/"
         
     | 
| 
      
 290 
     | 
    
         
            +
              ":x/:y" # matches "/foo/bar", "/bar/foo" etc.
         
     | 
| 
      
 291 
     | 
    
         
            +
              ":x/:y" # does not match "/foo", "/bar/"
         
     | 
| 
       204 
292 
     | 
    
         | 
| 
       205 
293 
     | 
    
         
             
            You can prefix colons:
         
     | 
| 
       206 
294 
     | 
    
         | 
| 
       207 
     | 
    
         
            -
              "foo:x/bar:y" matches "/food/bard", "/fool/bart", etc.
         
     | 
| 
       208 
     | 
    
         
            -
              "foo:x/bar:y" does not match "/foo/bart", "/fool/bar", etc.
         
     | 
| 
      
 295 
     | 
    
         
            +
              "foo:x/bar:y" # matches "/food/bard", "/fool/bart", etc.
         
     | 
| 
      
 296 
     | 
    
         
            +
              "foo:x/bar:y" # does not match "/foo/bart", "/fool/bar", etc.
         
     | 
| 
       209 
297 
     | 
    
         | 
| 
       210 
298 
     | 
    
         
             
            If any colons are used, the block will yield one argument for
         
     | 
| 
       211 
299 
     | 
    
         
             
            each segment matched containing the matched text.  So:
         
     | 
| 
       212 
300 
     | 
    
         | 
| 
       213 
     | 
    
         
            -
              "foo:x/:y" matching "/fool/bar" yields "l", "bar"
         
     | 
| 
      
 301 
     | 
    
         
            +
              "foo:x/:y" # matching "/fool/bar" yields "l", "bar"
         
     | 
| 
       214 
302 
     | 
    
         | 
| 
       215 
303 
     | 
    
         
             
            Colons that are not followed by a <tt>\\w</tt> character are matched literally:
         
     | 
| 
       216 
304 
     | 
    
         | 
| 
       217 
     | 
    
         
            -
              ":/a" matches "/:/a"
         
     | 
| 
      
 305 
     | 
    
         
            +
              ":/a" # matches "/:/a"
         
     | 
| 
       218 
306 
     | 
    
         | 
| 
       219 
307 
     | 
    
         
             
            Note that strings are regexp escaped before being used in a regular
         
     | 
| 
       220 
308 
     | 
    
         
             
            expression, so:
         
     | 
| 
       221 
309 
     | 
    
         | 
| 
       222 
     | 
    
         
            -
              "\\d+(/\\w+)?" matches " 
     | 
| 
       223 
     | 
    
         
            -
              "\\d 
     | 
| 
      
 310 
     | 
    
         
            +
              "\\d+(/\\w+)?" # matches "/\d+(/\w+)?"
         
     | 
| 
      
 311 
     | 
    
         
            +
              "\\d+(/\\w+)?" # does not match "/123/abc"
         
     | 
| 
       224 
312 
     | 
    
         | 
| 
       225 
313 
     | 
    
         
             
            === Regexp
         
     | 
| 
       226 
314 
     | 
    
         | 
| 
       227 
315 
     | 
    
         
             
            Regexps match one or more segments by looking for the pattern preceeded by a
         
     | 
| 
       228 
316 
     | 
    
         
             
            slash:
         
     | 
| 
       229 
317 
     | 
    
         | 
| 
       230 
     | 
    
         
            -
              /foo\w+/ matches "/foobar"
         
     | 
| 
       231 
     | 
    
         
            -
              /foo\w+/ does not match "/foo/bar"
         
     | 
| 
      
 318 
     | 
    
         
            +
              /foo\w+/ # matches "/foobar"
         
     | 
| 
      
 319 
     | 
    
         
            +
              /foo\w+/ # does not match "/foo/bar"
         
     | 
| 
       232 
320 
     | 
    
         | 
| 
       233 
321 
     | 
    
         
             
            If any patterns are captured by the regexp, they are yielded:
         
     | 
| 
       234 
322 
     | 
    
         | 
| 
       235 
     | 
    
         
            -
              /foo\w+/ matches "/foobar", yields nothing
         
     | 
| 
       236 
     | 
    
         
            -
              /foo(\w+)/ matches "/foobar", yields "bar" 
         
     | 
| 
      
 323 
     | 
    
         
            +
              /foo\w+/   # matches "/foobar", yields nothing
         
     | 
| 
      
 324 
     | 
    
         
            +
              /foo(\w+)/ # matches "/foobar", yields "bar" 
         
     | 
| 
       237 
325 
     | 
    
         | 
| 
       238 
326 
     | 
    
         
             
            === Symbol
         
     | 
| 
       239 
327 
     | 
    
         | 
| 
       240 
328 
     | 
    
         
             
            Symbols match any nonempty segment, yielding the segment except for the
         
     | 
| 
       241 
329 
     | 
    
         
             
            preceeding slash:
         
     | 
| 
       242 
330 
     | 
    
         | 
| 
       243 
     | 
    
         
            -
              :id matches "/foo" yields "foo"
         
     | 
| 
       244 
     | 
    
         
            -
              :id does not match "/"
         
     | 
| 
      
 331 
     | 
    
         
            +
              :id # matches "/foo" yields "foo"
         
     | 
| 
      
 332 
     | 
    
         
            +
              :id # does not match "/"
         
     | 
| 
       245 
333 
     | 
    
         | 
| 
       246 
334 
     | 
    
         
             
            === Proc
         
     | 
| 
       247 
335 
     | 
    
         | 
| 
       248 
336 
     | 
    
         
             
            Procs match unless they return false or nil:
         
     | 
| 
       249 
337 
     | 
    
         | 
| 
       250 
     | 
    
         
            -
              proc{true} matches anything
         
     | 
| 
       251 
     | 
    
         
            -
              proc{false} does not match anything
         
     | 
| 
      
 338 
     | 
    
         
            +
              proc{true}  # matches anything
         
     | 
| 
      
 339 
     | 
    
         
            +
              proc{false} # does not match anything
         
     | 
| 
       252 
340 
     | 
    
         | 
| 
       253 
341 
     | 
    
         
             
            Procs don't capture anything by default, but they can if you add
         
     | 
| 
       254 
342 
     | 
    
         
             
            the captured text to +r.captures+.
         
     | 
| 
         @@ -263,8 +351,8 @@ condition).  Evaluation stops at the first matcher that matches. 
     | 
|
| 
       263 
351 
     | 
    
         
             
            Additionally, if the matched object is a String, the string is yielded.
         
     | 
| 
       264 
352 
     | 
    
         
             
            This makes it easy to handle multiple strings without a Regexp:
         
     | 
| 
       265 
353 
     | 
    
         | 
| 
       266 
     | 
    
         
            -
               
     | 
| 
       267 
     | 
    
         
            -
              [] does not match anything
         
     | 
| 
      
 354 
     | 
    
         
            +
              ['page1', 'page2'] # matches "/page1", "/page2"
         
     | 
| 
      
 355 
     | 
    
         
            +
              []                 # does not match anything
         
     | 
| 
       268 
356 
     | 
    
         | 
| 
       269 
357 
     | 
    
         
             
            === Hash
         
     | 
| 
       270 
358 
     | 
    
         | 
| 
         @@ -276,12 +364,12 @@ block will be called with the value of the hash. 
     | 
|
| 
       276 
364 
     | 
    
         | 
| 
       277 
365 
     | 
    
         
             
              class App < Roda
         
     | 
| 
       278 
366 
     | 
    
         
             
                hash_matcher(:foo) do |v|
         
     | 
| 
       279 
     | 
    
         
            -
                  ...
         
     | 
| 
      
 367 
     | 
    
         
            +
                  # ...
         
     | 
| 
       280 
368 
     | 
    
         
             
                end
         
     | 
| 
       281 
369 
     | 
    
         | 
| 
       282 
370 
     | 
    
         
             
                route do |r|
         
     | 
| 
       283 
371 
     | 
    
         
             
                  r.on :foo=>'bar' do
         
     | 
| 
       284 
     | 
    
         
            -
                    ...
         
     | 
| 
      
 372 
     | 
    
         
            +
                    # ...
         
     | 
| 
       285 
373 
     | 
    
         
             
                  end
         
     | 
| 
       286 
374 
     | 
    
         
             
                end
         
     | 
| 
       287 
375 
     | 
    
         
             
              end
         
     | 
| 
         @@ -291,13 +379,13 @@ block will be called with the value of the hash. 
     | 
|
| 
       291 
379 
     | 
    
         
             
            The :all matcher matches if all of the entries in the given array matches. So
         
     | 
| 
       292 
380 
     | 
    
         | 
| 
       293 
381 
     | 
    
         
             
              r.on :all=>[:a, :b] do
         
     | 
| 
       294 
     | 
    
         
            -
                ...
         
     | 
| 
      
 382 
     | 
    
         
            +
                # ...
         
     | 
| 
       295 
383 
     | 
    
         
             
              end
         
     | 
| 
       296 
384 
     | 
    
         | 
| 
       297 
385 
     | 
    
         
             
            is the same as:
         
     | 
| 
       298 
386 
     | 
    
         | 
| 
       299 
387 
     | 
    
         
             
              r.on :a, :b do
         
     | 
| 
       300 
     | 
    
         
            -
                ...
         
     | 
| 
      
 388 
     | 
    
         
            +
                # ...
         
     | 
| 
       301 
389 
     | 
    
         
             
              end
         
     | 
| 
       302 
390 
     | 
    
         | 
| 
       303 
391 
     | 
    
         
             
            The reason it also exists as a separate hash matcher is so you can use it inside
         
     | 
| 
         @@ -312,34 +400,32 @@ Would match +/foo+ and +/foos/10+, but not +/foos+. 
     | 
|
| 
       312 
400 
     | 
    
         | 
| 
       313 
401 
     | 
    
         
             
            The :extension matcher matches any nonempty path ending with the given extension:
         
     | 
| 
       314 
402 
     | 
    
         | 
| 
       315 
     | 
    
         
            -
              :extension => "css" matches "/foo.css", "/bar.css"
         
     | 
| 
       316 
     | 
    
         
            -
              :extension => "css" does not match "/foo.css/x", "/foo.bar", "/.css"
         
     | 
| 
      
 403 
     | 
    
         
            +
              {:extension => "css"} # matches "/foo.css", "/bar.css"
         
     | 
| 
      
 404 
     | 
    
         
            +
              {:extension => "css"} # does not match "/foo.css/x", "/foo.bar", "/.css"
         
     | 
| 
       317 
405 
     | 
    
         | 
| 
       318 
     | 
    
         
            -
            This matcher yields the part before the extension. 
     | 
| 
       319 
     | 
    
         
            -
            matchers, this matcher assumes terminal behavior, it doesn't match if there
         
     | 
| 
       320 
     | 
    
         
            -
            are additional segments.
         
     | 
| 
      
 406 
     | 
    
         
            +
            This matcher yields the part before the extension.
         
     | 
| 
       321 
407 
     | 
    
         | 
| 
       322 
408 
     | 
    
         
             
            ==== :method
         
     | 
| 
       323 
409 
     | 
    
         | 
| 
       324 
410 
     | 
    
         
             
            This matches the method of the request.  You can provide an array to specify multiple
         
     | 
| 
       325 
411 
     | 
    
         
             
            request methods and match on any of them:
         
     | 
| 
       326 
412 
     | 
    
         | 
| 
       327 
     | 
    
         
            -
              :method => :post matches POST
         
     | 
| 
       328 
     | 
    
         
            -
              :method =>  
     | 
| 
      
 413 
     | 
    
         
            +
              {:method => :post}             # matches POST
         
     | 
| 
      
 414 
     | 
    
         
            +
              {:method => ['post', 'patch']} # matches POST and PATCH
         
     | 
| 
       329 
415 
     | 
    
         | 
| 
       330 
416 
     | 
    
         
             
            ==== :param
         
     | 
| 
       331 
417 
     | 
    
         | 
| 
       332 
418 
     | 
    
         
             
            The :param matcher matches if the given parameter is present, even if empty.
         
     | 
| 
       333 
419 
     | 
    
         | 
| 
       334 
     | 
    
         
            -
              :param => "user" matches "/foo?user=bar", "/foo?user="
         
     | 
| 
       335 
     | 
    
         
            -
              :param => "user" does not matches "/foo"
         
     | 
| 
      
 420 
     | 
    
         
            +
              {:param => "user"} # matches "/foo?user=bar", "/foo?user="
         
     | 
| 
      
 421 
     | 
    
         
            +
              {:param => "user"} # does not matches "/foo"
         
     | 
| 
       336 
422 
     | 
    
         | 
| 
       337 
423 
     | 
    
         
             
            ==== :param!
         
     | 
| 
       338 
424 
     | 
    
         | 
| 
       339 
425 
     | 
    
         
             
            The :param! matcher matches if the given parameter is present and not empty.
         
     | 
| 
       340 
426 
     | 
    
         | 
| 
       341 
     | 
    
         
            -
              :param! => "user" matches "/foo?user=bar"
         
     | 
| 
       342 
     | 
    
         
            -
              :param! => "user" does not matches "/foo", "/foo?user="
         
     | 
| 
      
 427 
     | 
    
         
            +
              {:param! => "user"} # matches "/foo?user=bar"
         
     | 
| 
      
 428 
     | 
    
         
            +
              {:param! => "user"} # does not matches "/foo", "/foo?user="
         
     | 
| 
       343 
429 
     | 
    
         | 
| 
       344 
430 
     | 
    
         
             
            === false, nil
         
     | 
| 
       345 
431 
     | 
    
         | 
| 
         @@ -361,10 +447,8 @@ You can always set the status code manually via the status attribute 
     | 
|
| 
       361 
447 
     | 
    
         
             
            for the response.
         
     | 
| 
       362 
448 
     | 
    
         | 
| 
       363 
449 
     | 
    
         
             
              route do |r|
         
     | 
| 
       364 
     | 
    
         
            -
                r.get do
         
     | 
| 
       365 
     | 
    
         
            -
                   
     | 
| 
       366 
     | 
    
         
            -
                    response.status = 200
         
     | 
| 
       367 
     | 
    
         
            -
                  end
         
     | 
| 
      
 450 
     | 
    
         
            +
                r.get "hello" do
         
     | 
| 
      
 451 
     | 
    
         
            +
                  response.status = 200
         
     | 
| 
       368 
452 
     | 
    
         
             
                end
         
     | 
| 
       369 
453 
     | 
    
         
             
              end
         
     | 
| 
       370 
454 
     | 
    
         | 
| 
         @@ -372,22 +456,27 @@ for the response. 
     | 
|
| 
       372 
456 
     | 
    
         | 
| 
       373 
457 
     | 
    
         
             
            The main match method is +r.on+, but as displayed above, you can also
         
     | 
| 
       374 
458 
     | 
    
         
             
            use +r.get+ or +r.post+.  When called without any arguments, these
         
     | 
| 
       375 
     | 
    
         
            -
             
     | 
| 
      
 459 
     | 
    
         
            +
            match as long as the request has the appropriate method, so:
         
     | 
| 
      
 460 
     | 
    
         
            +
             
     | 
| 
      
 461 
     | 
    
         
            +
              r.get do end
         
     | 
| 
       376 
462 
     | 
    
         | 
| 
       377 
     | 
    
         
            -
             
     | 
| 
      
 463 
     | 
    
         
            +
            matches any +GET+ request, and
         
     | 
| 
       378 
464 
     | 
    
         | 
| 
       379 
     | 
    
         
            -
             
     | 
| 
      
 465 
     | 
    
         
            +
              r.post do end
         
     | 
| 
       380 
466 
     | 
    
         | 
| 
       381 
     | 
    
         
            -
             
     | 
| 
      
 467 
     | 
    
         
            +
            matches any +POST+ request
         
     | 
| 
       382 
468 
     | 
    
         | 
| 
       383 
     | 
    
         
            -
            If any arguments are given to the method, these  
     | 
| 
       384 
     | 
    
         
            -
            the request  
     | 
| 
      
 469 
     | 
    
         
            +
            If any arguments are given to the method, these match only
         
     | 
| 
      
 470 
     | 
    
         
            +
            if the request method matches, all arguments match, and
         
     | 
| 
      
 471 
     | 
    
         
            +
            only the path has been fully matched by the arguments.  So:
         
     | 
| 
       385 
472 
     | 
    
         | 
| 
       386 
     | 
    
         
            -
             
     | 
| 
      
 473 
     | 
    
         
            +
              r.post "" do end
         
     | 
| 
       387 
474 
     | 
    
         | 
| 
       388 
     | 
    
         
            -
             
     | 
| 
      
 475 
     | 
    
         
            +
            matches only +POST+ requests where the current path is +/+.
         
     | 
| 
       389 
476 
     | 
    
         | 
| 
       390 
     | 
    
         
            -
             
     | 
| 
      
 477 
     | 
    
         
            +
              r.get "a/b" do end
         
     | 
| 
      
 478 
     | 
    
         
            +
             
     | 
| 
      
 479 
     | 
    
         
            +
            matches only +GET+ requests where the current path is +/a/b+.
         
     | 
| 
       391 
480 
     | 
    
         | 
| 
       392 
481 
     | 
    
         
             
            The reason for this difference in behavior is that if you are not
         
     | 
| 
       393 
482 
     | 
    
         
             
            providing any arguments, you probably don't want to to also test
         
     | 
| 
         @@ -400,17 +489,17 @@ you do want, you can provide true as an argument: 
     | 
|
| 
       400 
489 
     | 
    
         
             
              end
         
     | 
| 
       401 
490 
     | 
    
         | 
| 
       402 
491 
     | 
    
         
             
            If you want to match the request method and do a partial match
         
     | 
| 
       403 
     | 
    
         
            -
            on the request path, you need to use 
     | 
| 
       404 
     | 
    
         
            -
            hash matcher:
         
     | 
| 
      
 492 
     | 
    
         
            +
            on the request path instead of a full match, you need to use
         
     | 
| 
      
 493 
     | 
    
         
            +
            +r.on+ with the <tt>:method</tt> hash matcher:
         
     | 
| 
       405 
494 
     | 
    
         | 
| 
       406 
495 
     | 
    
         
             
              r.on "foo", :method=>:get do # Matches GET /foo(/.*)?
         
     | 
| 
       407 
     | 
    
         
            -
               
     | 
| 
      
 496 
     | 
    
         
            +
              end
         
     | 
| 
       408 
497 
     | 
    
         | 
| 
       409 
498 
     | 
    
         
             
            == Root Method
         
     | 
| 
       410 
499 
     | 
    
         | 
| 
       411 
500 
     | 
    
         
             
            As displayed above, you can also use +r.root+ as a match method.  This
         
     | 
| 
       412 
     | 
    
         
            -
            method matches  
     | 
| 
       413 
     | 
    
         
            -
            except that it does not consume the +/+ from the path.
         
     | 
| 
      
 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.
         
     | 
| 
       414 
503 
     | 
    
         | 
| 
       415 
504 
     | 
    
         
             
            Unlike the other matching methods, +r.root+ takes no arguments.
         
     | 
| 
       416 
505 
     | 
    
         | 
| 
         @@ -438,8 +527,8 @@ methods, or via plugins. 
     | 
|
| 
       438 
527 
     | 
    
         | 
| 
       439 
528 
     | 
    
         
             
            == Pollution
         
     | 
| 
       440 
529 
     | 
    
         | 
| 
       441 
     | 
    
         
            -
            Roda tries very hard to avoid polluting the scope  
     | 
| 
       442 
     | 
    
         
            -
            block 
     | 
| 
      
 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
         
     | 
| 
       443 
532 
     | 
    
         
             
            the +route+ block are <tt>@_request</tt> and <tt>@_response</tt>.  The only methods defined
         
     | 
| 
       444 
533 
     | 
    
         
             
            (beyond the default methods for +Object+) are: +env+, +opts+, +request+,
         
     | 
| 
       445 
534 
     | 
    
         
             
            +response+, +call+, +session+, and +_route+ (private). Constants inside the
         
     | 
| 
         @@ -476,8 +565,8 @@ in the request (via POST or QUERY_STRING) and it pushes the value as a capture. 
     | 
|
| 
       476 
565 
     | 
    
         | 
| 
       477 
566 
     | 
    
         
             
            == Composition
         
     | 
| 
       478 
567 
     | 
    
         | 
| 
       479 
     | 
    
         
            -
            You can mount  
     | 
| 
       480 
     | 
    
         
            -
             
     | 
| 
      
 568 
     | 
    
         
            +
            You can mount any Rack app (including another Roda app), with its own middlewares,
         
     | 
| 
      
 569 
     | 
    
         
            +
            inside a Roda app, using +r.run+:
         
     | 
| 
       481 
570 
     | 
    
         | 
| 
       482 
571 
     | 
    
         
             
              class API < Roda
         
     | 
| 
       483 
572 
     | 
    
         
             
                use SomeMiddleware
         
     | 
| 
         @@ -499,13 +588,24 @@ via +r.run+: 
     | 
|
| 
       499 
588 
     | 
    
         | 
| 
       500 
589 
     | 
    
         
             
              run App.app
         
     | 
| 
       501 
590 
     | 
    
         | 
| 
       502 
     | 
    
         
            -
             
     | 
| 
      
 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.
         
     | 
| 
      
 594 
     | 
    
         
            +
             
     | 
| 
      
 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.
         
     | 
| 
      
 598 
     | 
    
         
            +
             
     | 
| 
      
 599 
     | 
    
         
            +
            === multi_route plugin
         
     | 
| 
      
 600 
     | 
    
         
            +
             
     | 
| 
      
 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
         
     | 
| 
       503 
603 
     | 
    
         
             
            the route block:
         
     | 
| 
       504 
604 
     | 
    
         | 
| 
       505 
605 
     | 
    
         
             
              class App < Roda
         
     | 
| 
       506 
606 
     | 
    
         
             
                plugin :multi_route
         
     | 
| 
       507 
607 
     | 
    
         | 
| 
       508 
     | 
    
         
            -
                route  
     | 
| 
      
 608 
     | 
    
         
            +
                route "api" do |r|
         
     | 
| 
       509 
609 
     | 
    
         
             
                  r.is do
         
     | 
| 
       510 
610 
     | 
    
         
             
                    # ...
         
     | 
| 
       511 
611 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -513,13 +613,16 @@ the route block: 
     | 
|
| 
       513 
613 
     | 
    
         | 
| 
       514 
614 
     | 
    
         
             
                route do |r|
         
     | 
| 
       515 
615 
     | 
    
         
             
                  r.on "api" do
         
     | 
| 
       516 
     | 
    
         
            -
                    route  
     | 
| 
      
 616 
     | 
    
         
            +
                    r.route "api"
         
     | 
| 
       517 
617 
     | 
    
         
             
                  end
         
     | 
| 
       518 
618 
     | 
    
         
             
                end
         
     | 
| 
       519 
619 
     | 
    
         
             
              end
         
     | 
| 
       520 
620 
     | 
    
         | 
| 
       521 
621 
     | 
    
         
             
              run App.app
         
     | 
| 
       522 
622 
     | 
    
         | 
| 
      
 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.
         
     | 
| 
      
 625 
     | 
    
         
            +
             
     | 
| 
       523 
626 
     | 
    
         
             
            == Testing
         
     | 
| 
       524 
627 
     | 
    
         | 
| 
       525 
628 
     | 
    
         
             
            It is very easy to test Roda with {Rack::Test}[https://github.com/brynary/rack-test]
         
     | 
| 
         @@ -656,6 +759,8 @@ Note that unlike most other render options, the :escape option 
     | 
|
| 
       656 
759 
     | 
    
         
             
            must be passed to the <tt>plugin :render</tt> call, it won't be
         
     | 
| 
       657 
760 
     | 
    
         
             
            respected if added later.
         
     | 
| 
       658 
761 
     | 
    
         | 
| 
      
 762 
     | 
    
         
            +
            This support requires {Erubis}[http://www.kuwata-lab.com/erubis/].
         
     | 
| 
      
 763 
     | 
    
         
            +
             
     | 
| 
       659 
764 
     | 
    
         
             
            === Other
         
     | 
| 
       660 
765 
     | 
    
         | 
| 
       661 
766 
     | 
    
         
             
            For prevention of some other vulnerabilities, such as click-jacking,
         
     | 
| 
         @@ -687,6 +792,8 @@ content_for :: Allows storage of content in one template and retrieval of 
     | 
|
| 
       687 
792 
     | 
    
         
             
            csrf :: Adds CSRF protection and helper methods using
         
     | 
| 
       688 
793 
     | 
    
         
             
                    {rack_csrf}[https://github.com/baldowl/rack_csrf].
         
     | 
| 
       689 
794 
     | 
    
         
             
            default_headers :: Override the default response headers used.
         
     | 
| 
      
 795 
     | 
    
         
            +
            error_email :: Adds an +error_email+ method that can be used to email when
         
     | 
| 
      
 796 
     | 
    
         
            +
                           an exception is raised.
         
     | 
| 
       690 
797 
     | 
    
         
             
            error_handler :: Adds a +error+ block that is called for all responses that
         
     | 
| 
       691 
798 
     | 
    
         
             
                             raise exceptions.
         
     | 
| 
       692 
799 
     | 
    
         
             
            flash :: Adds a flash handler.
         
     | 
| 
         @@ -710,6 +817,7 @@ not_found :: Adds a +not_found+ block that is called for all 404 responses 
     | 
|
| 
       710 
817 
     | 
    
         
             
                         without bodies.
         
     | 
| 
       711 
818 
     | 
    
         
             
            pass :: Adds a pass method allowing you to skip the current +r.on+ block as if
         
     | 
| 
       712 
819 
     | 
    
         
             
                    it did not match.
         
     | 
| 
      
 820 
     | 
    
         
            +
            path :: Adds support for named paths.
         
     | 
| 
       713 
821 
     | 
    
         
             
            per_thread_caching :: Switches the thread-safe cache from a shared cache to a
         
     | 
| 
       714 
822 
     | 
    
         
             
                                  per-thread cache.
         
     | 
| 
       715 
823 
     | 
    
         
             
            render :: Adds support for rendering templates via tilt, as described above.
         
     |