maveric 0.1.0 → 0.2.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/maveric.rb +350 -493
 - data/maveric/extensions.rb +94 -0
 - data/maveric/mongrel.rb +2 -2
 - data/maveric/sessions.rb +73 -0
 - metadata +5 -4
 - data/maveric/stadik-impl.rb +0 -113
 
    
        data/maveric.rb
    CHANGED
    
    | 
         @@ -1,11 +1,29 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ##
         
     | 
| 
       2 
2 
     | 
    
         
             
            # = Maveric: A simple, non-magical, framework
         
     | 
| 
       3 
3 
     | 
    
         
             
            #
         
     | 
| 
      
 4 
     | 
    
         
            +
            # == Resources
         
     | 
| 
      
 5 
     | 
    
         
            +
            #
         
     | 
| 
      
 6 
     | 
    
         
            +
            # Maveric can normally be found on {rubyforge}[http://maveric.rubyforge.org/]
         
     | 
| 
      
 7 
     | 
    
         
            +
            # with it's project page {here}[http://rubyforge.org/projects/maveric/].
         
     | 
| 
      
 8 
     | 
    
         
            +
            #
         
     | 
| 
      
 9 
     | 
    
         
            +
            # Maveric is also listed at the RAA as
         
     | 
| 
      
 10 
     | 
    
         
            +
            # {maveric}[http://raa.ruby-lang.org/project/maveric/]. This page lags a bit
         
     | 
| 
      
 11 
     | 
    
         
            +
            # behind rubyforge.
         
     | 
| 
      
 12 
     | 
    
         
            +
            #
         
     | 
| 
      
 13 
     | 
    
         
            +
            # Maveric's home away from home is http://code.stadik.net which contains
         
     | 
| 
      
 14 
     | 
    
         
            +
            # many other things.
         
     | 
| 
      
 15 
     | 
    
         
            +
            #
         
     | 
| 
       4 
16 
     | 
    
         
             
            # == Version
         
     | 
| 
       5 
17 
     | 
    
         
             
            #
         
     | 
| 
       6 
     | 
    
         
            -
            # This is 0.1.0  
     | 
| 
      
 18 
     | 
    
         
            +
            # This is 0.1.0, the first real release of Maveric. It's rough around the edges
         
     | 
| 
       7 
19 
     | 
    
         
             
            # and several squishy bits in the middle. At the moment it's still operation
         
     | 
| 
       8 
20 
     | 
    
         
             
            # conceptualization over algorithm implementation. It's usable, but kinda.
         
     | 
| 
      
 21 
     | 
    
         
            +
            #
         
     | 
| 
      
 22 
     | 
    
         
            +
            # Ahh, 0.2.0, wherein we reevaluate ourselves and our ways and eliminate the
         
     | 
| 
      
 23 
     | 
    
         
            +
            # cruft and improve our efficiency. We have a new implementation of Routing
         
     | 
| 
      
 24 
     | 
    
         
            +
            # going on, they're now regexps. The ServerError class has been removed, now any subclass of Exception can be raised. One of the larger differences is greater
         
     | 
| 
      
 25 
     | 
    
         
            +
            # customization of Maveric and Controller instances through extending methods.
         
     | 
| 
      
 26 
     | 
    
         
            +
            # These are touched upon in their respective docs. Have fun!
         
     | 
| 
       9 
27 
     | 
    
         
             
            # 
         
     | 
| 
       10 
28 
     | 
    
         
             
            # == Authors
         
     | 
| 
       11 
29 
     | 
    
         
             
            # 
         
     | 
| 
         @@ -57,14 +75,22 @@ 
     | 
|
| 
       57 
75 
     | 
    
         
             
            # 
         
     | 
| 
       58 
76 
     | 
    
         
             
            # Because ehird from #ruby-lang was whining about it so much I removed its
         
     | 
| 
       59 
77 
     | 
    
         
             
            # dependancy on Mongrel sooner than later. Maveric should now be very maveric.
         
     | 
| 
      
 78 
     | 
    
         
            +
            #
         
     | 
| 
      
 79 
     | 
    
         
            +
            # Because Maveric 0.1.0 worked, but still didn't do things the way I wanted
         
     | 
| 
      
 80 
     | 
    
         
            +
            # I revised and refactored codes and algorithms into 0.2.0 which will hopefully
         
     | 
| 
      
 81 
     | 
    
         
            +
            # be all that I want. Everything beyond 1.0.0 will be improvements and
         
     | 
| 
      
 82 
     | 
    
         
            +
            # extensions.
         
     | 
| 
       60 
83 
     | 
    
         
             
            # 
         
     | 
| 
       61 
84 
     | 
    
         
             
            # = Features
         
     | 
| 
       62 
     | 
    
         
            -
            # *  
     | 
| 
      
 85 
     | 
    
         
            +
            # * Optional sessions
         
     | 
| 
       63 
86 
     | 
    
         
             
            # * Flexible and strong route setup
         
     | 
| 
       64 
87 
     | 
    
         
             
            # * Sharing of a Controller between Maveric instances is facilitated
         
     | 
| 
       65 
88 
     | 
    
         
             
            # * Inheritance is highly respected
         
     | 
| 
       66 
89 
     | 
    
         
             
            # 
         
     | 
| 
       67 
90 
     | 
    
         
             
            # == Not so Maveric
         
     | 
| 
      
 91 
     | 
    
         
            +
            #
         
     | 
| 
      
 92 
     | 
    
         
            +
            # NOTE: Maveric 0.2.0 does not include extension enablers, further releases
         
     | 
| 
      
 93 
     | 
    
         
            +
            # should include them.
         
     | 
| 
       68 
94 
     | 
    
         
             
            # 
         
     | 
| 
       69 
95 
     | 
    
         
             
            # For these examples we will utilize the simplest functional Maveric possible
         
     | 
| 
       70 
96 
     | 
    
         
             
            #   require 'maveric'
         
     | 
| 
         @@ -101,25 +127,9 @@ 
     | 
|
| 
       101 
127 
     | 
    
         
             
            # pointless time checks in place. Anything greater than the WARN level on the
         
     | 
| 
       102 
128 
     | 
    
         
             
            # logging output tends to output a good deal of information. DEBUG is not for
         
     | 
| 
       103 
129 
     | 
    
         
             
            # the meek.
         
     | 
| 
       104 
     | 
    
         
            -
             
     | 
| 
       105 
130 
     | 
    
         
             
            require 'log4r'
         
     | 
| 
       106 
     | 
    
         
            -
            require 'benchmark'
         
     | 
| 
       107 
131 
     | 
    
         
             
            require 'stringio'
         
     | 
| 
       108 
     | 
    
         
            -
             
     | 
| 
       109 
     | 
    
         
            -
            class Module
         
     | 
| 
       110 
     | 
    
         
            -
              protected
         
     | 
| 
       111 
     | 
    
         
            -
              ##
         
     | 
| 
       112 
     | 
    
         
            -
              # Decends through the heirarchy of classes and modules looking fot
         
     | 
| 
       113 
     | 
    
         
            -
              # objects in constants that &test[const] == true
         
     | 
| 
       114 
     | 
    
         
            -
              def nested_search d=0, &test
         
     | 
| 
       115 
     | 
    
         
            -
                constants.map do |c| c, r = const_get(c), []
         
     | 
| 
       116 
     | 
    
         
            -
                  next if c == self
         
     | 
| 
       117 
     | 
    
         
            -
                  r << c if test[c]
         
     | 
| 
       118 
     | 
    
         
            -
                  r.concat c.nested_search(d+1, &test) if c.is_a? Class or c.is_a? Module
         
     | 
| 
       119 
     | 
    
         
            -
                  r
         
     | 
| 
       120 
     | 
    
         
            -
                end.flatten.compact
         
     | 
| 
       121 
     | 
    
         
            -
              end
         
     | 
| 
       122 
     | 
    
         
            -
            end
         
     | 
| 
      
 132 
     | 
    
         
            +
            require 'maveric/extensions'
         
     | 
| 
       123 
133 
     | 
    
         | 
| 
       124 
134 
     | 
    
         
             
            ##
         
     | 
| 
       125 
135 
     | 
    
         
             
            # = The Maveric: Yeargh.
         
     | 
| 
         @@ -130,6 +140,7 @@ end 
     | 
|
| 
       130 
140 
     | 
    
         
             
            # 
         
     | 
| 
       131 
141 
     | 
    
         
             
            # = Usage
         
     | 
| 
       132 
142 
     | 
    
         
             
            # We could technically have a running Maveric with:
         
     | 
| 
      
 143 
     | 
    
         
            +
            #
         
     | 
| 
       133 
144 
     | 
    
         
             
            #   require 'maveric'
         
     | 
| 
       134 
145 
     | 
    
         
             
            #   class Maveric::Index < Maveric::Controller
         
     | 
| 
       135 
146 
     | 
    
         
             
            #     def get
         
     | 
| 
         @@ -137,46 +148,29 @@ end 
     | 
|
| 
       137 
148 
     | 
    
         
             
            #     end
         
     | 
| 
       138 
149 
     | 
    
         
             
            #   end
         
     | 
| 
       139 
150 
     | 
    
         
             
            #   maveric = Maveric.new # I'm a real boy now!
         
     | 
| 
       140 
     | 
    
         
            -
            # 
     | 
| 
      
 151 
     | 
    
         
            +
            #
         
     | 
| 
      
 152 
     | 
    
         
            +
            # but that's not very useful.
         
     | 
| 
       141 
153 
     | 
    
         
             
            class Maveric
         
     | 
| 
      
 154 
     | 
    
         
            +
              ## Standard end of line for HTTP
         
     | 
| 
       142 
155 
     | 
    
         
             
              EOL="\r\n"
         
     | 
| 
      
 156 
     | 
    
         
            +
              ## Group 1 wil contain a boundary for multipart/form-data bodies.
         
     | 
| 
       143 
157 
     | 
    
         
             
              MP_BOUND_REGEX = /\Amultipart\/form-data.*boundary=\"?([^\";, ]+)\"?/n
         
     | 
| 
       144 
158 
     | 
    
         | 
| 
       145 
     | 
    
         
            -
               
     | 
| 
       146 
     | 
    
         
            -
               
     | 
| 
       147 
     | 
    
         
            -
              @log.level = Log4r::INFO
         
     | 
| 
       148 
     | 
    
         
            -
              #@sessions = Hash.new {|h,k| s = Maveric::Session.new; h[s.id]=s; }
         
     | 
| 
       149 
     | 
    
         
            -
              @@sessions = Hash.new {|h,k| s = Maveric::Session.new; h[s.id]=s; }
         
     | 
| 
       150 
     | 
    
         
            -
             
     | 
| 
       151 
     | 
    
         
            -
              @log.info "#{self.class} integrated at #{Time.now}"
         
     | 
| 
       152 
     | 
    
         
            -
             
     | 
| 
      
 159 
     | 
    
         
            +
              # I hate putting utility methods here, rather than in some module, but for
         
     | 
| 
      
 160 
     | 
    
         
            +
              # somereason things aren't working as they should that way.
         
     | 
| 
       153 
161 
     | 
    
         
             
              class << self
         
     | 
| 
       154 
     | 
    
         
            -
                ##
         
     | 
| 
       155 
     | 
    
         
            -
                 
     | 
| 
       156 
     | 
    
         
            -
             
     | 
| 
       157 
     | 
    
         
            -
             
     | 
| 
       158 
     | 
    
         
            -
             
     | 
| 
       159 
     | 
    
         
            -
             
     | 
| 
       160 
     | 
    
         
            -
             
     | 
| 
       161 
     | 
    
         
            -
                def inherited klass
         
     | 
| 
       162 
     | 
    
         
            -
                  Maveric.log.info "Maveric: #{klass} inherits from #{self}."
         
     | 
| 
       163 
     | 
    
         
            -
                  # By default a Maveric's logger is its parent's
         
     | 
| 
       164 
     | 
    
         
            -
                  klass.instance_variable_set :@log, @log
         
     | 
| 
       165 
     | 
    
         
            -
                  parent = self
         
     | 
| 
       166 
     | 
    
         
            -
                  klass.class_eval do
         
     | 
| 
       167 
     | 
    
         
            -
                    const_set(:Models, Module.new).
         
     | 
| 
       168 
     | 
    
         
            -
                      module_eval { include parent::Models }
         
     | 
| 
       169 
     | 
    
         
            -
                    const_set(:Views, Module.new).
         
     | 
| 
       170 
     | 
    
         
            -
                      module_eval { include parent::Views }
         
     | 
| 
      
 162 
     | 
    
         
            +
                ## Builds a logging object if there's not one yet, then returns it.
         
     | 
| 
      
 163 
     | 
    
         
            +
                def log
         
     | 
| 
      
 164 
     | 
    
         
            +
                  unless defined? @@maveric_logger
         
     | 
| 
      
 165 
     | 
    
         
            +
                    @@maveric_logger = Log4r::Logger.new 'mvc'
         
     | 
| 
      
 166 
     | 
    
         
            +
                    @@maveric_logger.outputters = Log4r::Outputter['stderr']
         
     | 
| 
      
 167 
     | 
    
         
            +
                    @@maveric_logger.level = Log4r::INFO
         
     | 
| 
      
 168 
     | 
    
         
            +
                    @@maveric_logger.info "#{self} integrated at #{Time.now}"
         
     | 
| 
       171 
169 
     | 
    
         
             
                  end
         
     | 
| 
      
 170 
     | 
    
         
            +
                  @@maveric_logger
         
     | 
| 
       172 
171 
     | 
    
         
             
                end
         
     | 
| 
       173 
172 
     | 
    
         | 
| 
       174 
     | 
    
         
            -
                 
     | 
| 
       175 
     | 
    
         
            -
             
     | 
| 
       176 
     | 
    
         
            -
                def sessions; @@sessions; end
         
     | 
| 
       177 
     | 
    
         
            -
             
     | 
| 
       178 
     | 
    
         
            -
                ##
         
     | 
| 
       179 
     | 
    
         
            -
                # Performs URI escaping.
         
     | 
| 
      
 173 
     | 
    
         
            +
                ## Performs URI escaping.
         
     | 
| 
       180 
174 
     | 
    
         
             
                def escape(s)
         
     | 
| 
       181 
175 
     | 
    
         
             
                  s.to_s.gsub(/([^ a-zA-Z0-9_.-]+)/n) {
         
     | 
| 
       182 
176 
     | 
    
         
             
                    '%'+$1.unpack('H2'*$1.size).join('%').upcase
         
     | 
| 
         @@ -194,21 +188,23 @@ class Maveric 
     | 
|
| 
       194 
188 
     | 
    
         
             
                # Parses a query string by breaking it up around the
         
     | 
| 
       195 
189 
     | 
    
         
             
                # delimiting characters.  You can also use this to parse
         
     | 
| 
       196 
190 
     | 
    
         
             
                # cookies by changing the characters used in the second
         
     | 
| 
       197 
     | 
    
         
            -
                # parameter (which defaults to ';,'.
         
     | 
| 
      
 191 
     | 
    
         
            +
                # parameter (which defaults to ';,').
         
     | 
| 
      
 192 
     | 
    
         
            +
                #
         
     | 
| 
      
 193 
     | 
    
         
            +
                # This will return a hash of parameters, values being contained in an
         
     | 
| 
      
 194 
     | 
    
         
            +
                # array. As a warning, the default value is an empty array, not nil.
         
     | 
| 
       198 
195 
     | 
    
         
             
                def query_parse(qs, delim = '&;')
         
     | 
| 
       199 
     | 
    
         
            -
                  (qs||'').split(/[#{delim}] */n).inject( 
     | 
| 
      
 196 
     | 
    
         
            +
                  (qs||'').split(/[#{delim}] */n).inject(Hash.new([])) { |h,p|
         
     | 
| 
       200 
197 
     | 
    
         
             
                    k, v = unescape(p).split('=',2)
         
     | 
| 
       201 
     | 
    
         
            -
                     
     | 
| 
       202 
     | 
    
         
            -
                      if h[k].is_a? Array then h[k] << v
         
     | 
| 
       203 
     | 
    
         
            -
                      else h[k] = [h[k], v] end
         
     | 
| 
       204 
     | 
    
         
            -
                    else h[k] = v end
         
     | 
| 
      
 198 
     | 
    
         
            +
                    (h[k]||=[]) << v
         
     | 
| 
       205 
199 
     | 
    
         
             
                    h
         
     | 
| 
       206 
200 
     | 
    
         
             
                  }
         
     | 
| 
       207 
201 
     | 
    
         
             
                end
         
     | 
| 
       208 
202 
     | 
    
         | 
| 
       209 
203 
     | 
    
         
             
                ##
         
     | 
| 
       210 
204 
     | 
    
         
             
                # Parse a multipart/form-data entity. Adapated from cgi.rb. The body
         
     | 
| 
       211 
     | 
    
         
            -
                # argument may either be a StringIO or a IO of  
     | 
| 
      
 205 
     | 
    
         
            +
                # argument may either be a StringIO or a IO of subclass thereof.
         
     | 
| 
      
 206 
     | 
    
         
            +
                #
         
     | 
| 
      
 207 
     | 
    
         
            +
                # Might need to be rehauled to match query_parse's behaviour.
         
     | 
| 
       212 
208 
     | 
    
         
             
                def parse_multipart boundary, body
         
     | 
| 
       213 
209 
     | 
    
         
             
                  ::Maveric.type_check :body, body, IO
         
     | 
| 
       214 
210 
     | 
    
         
             
                  values = {}
         
     | 
| 
         @@ -239,12 +235,11 @@ class Maveric 
     | 
|
| 
       239 
235 
     | 
    
         
             
                  values
         
     | 
| 
       240 
236 
     | 
    
         
             
                end
         
     | 
| 
       241 
237 
     | 
    
         | 
| 
       242 
     | 
    
         
            -
                ## 
     | 
| 
       243 
     | 
    
         
            -
                 
     | 
| 
       244 
     | 
    
         
            -
             
     | 
| 
       245 
     | 
    
         
            -
                 
     | 
| 
       246 
     | 
    
         
            -
             
     | 
| 
       247 
     | 
    
         
            -
                ## So we don't have ginormous test+raise statements everywhere.
         
     | 
| 
      
 238 
     | 
    
         
            +
                ##
         
     | 
| 
      
 239 
     | 
    
         
            +
                # I have a penchant for static typing, but just as a general assertion
         
     | 
| 
      
 240 
     | 
    
         
            +
                # and insurance that the correct types of data are being passed I created
         
     | 
| 
      
 241 
     | 
    
         
            +
                # this little checking method. It will test value to be an instance of
         
     | 
| 
      
 242 
     | 
    
         
            +
                # any of the trailing class, or if the block provided evalutates as true.
         
     | 
| 
       248 
243 
     | 
    
         
             
                def type_check name, value, *klasses, &test
         
     | 
| 
       249 
244 
     | 
    
         
             
                  if klasses.any? {|klass| value.is_a? klass } then return true
         
     | 
| 
       250 
245 
     | 
    
         
             
                  elsif test and test[value] then return true
         
     | 
| 
         @@ -253,517 +248,379 @@ class Maveric 
     | 
|
| 
       253 
248 
     | 
    
         
             
                      " got #{value.class}:#{value.inspect}."
         
     | 
| 
       254 
249 
     | 
    
         
             
                  end
         
     | 
| 
       255 
250 
     | 
    
         
             
                end
         
     | 
| 
       256 
     | 
    
         
            -
              end
         
     | 
| 
       257 
251 
     | 
    
         | 
| 
       258 
     | 
    
         
            -
             
     | 
| 
       259 
     | 
    
         
            -
             
     | 
| 
       260 
     | 
    
         
            -
             
     | 
| 
       261 
     | 
    
         
            -
             
     | 
| 
       262 
     | 
    
         
            -
             
     | 
| 
       263 
     | 
    
         
            -
             
     | 
| 
       264 
     | 
    
         
            -
             
     | 
| 
       265 
     | 
    
         
            -
             
     | 
| 
       266 
     | 
    
         
            -
             
     | 
| 
       267 
     | 
    
         
            -
             
     | 
| 
       268 
     | 
    
         
            -
             
     | 
| 
       269 
     | 
    
         
            -
             
     | 
| 
       270 
     | 
    
         
            -
             
     | 
| 
       271 
     | 
    
         
            -
                # By default we use a global session repository
         
     | 
| 
       272 
     | 
    
         
            -
                @sessions = @@sessions
         
     | 
| 
       273 
     | 
    
         
            -
             
     | 
| 
       274 
     | 
    
         
            -
                # defualt settings
         
     | 
| 
       275 
     | 
    
         
            -
                @path_prefix = ''
         
     | 
| 
       276 
     | 
    
         
            -
                # let's hande some options!
         
     | 
| 
       277 
     | 
    
         
            -
                if (hopts = opts[-1]).is_a? Hash
         
     | 
| 
       278 
     | 
    
         
            -
                  # should not end with / !!!!!
         
     | 
| 
       279 
     | 
    
         
            -
                  @path_prefix = hopts[:path_prefix] if hopts.key? :path_prefix
         
     | 
| 
      
 252 
     | 
    
         
            +
                ##################### Non-utility methods
         
     | 
| 
      
 253 
     | 
    
         
            +
             
     | 
| 
      
 254 
     | 
    
         
            +
                ##
         
     | 
| 
      
 255 
     | 
    
         
            +
                # A recursive method to hunt out subclasses of Controller nested
         
     | 
| 
      
 256 
     | 
    
         
            +
                # within a Maveric subclass. Used in the setting up of autoroutes.
         
     | 
| 
      
 257 
     | 
    
         
            +
                def nested_controllers realm=self, stk=[]
         
     | 
| 
      
 258 
     | 
    
         
            +
                  stk << realm #We don't need to visit the same thing twice.
         
     | 
| 
      
 259 
     | 
    
         
            +
                  realm.constants.map do |c|
         
     | 
| 
      
 260 
     | 
    
         
            +
                    next if stk.include?(c = realm.const_get(c)) or not c.is_a? Module
         
     | 
| 
      
 261 
     | 
    
         
            +
                    a = []
         
     | 
| 
      
 262 
     | 
    
         
            +
                    a << c if c < ::Maveric::Controller
         
     | 
| 
      
 263 
     | 
    
         
            +
                    a += nested_controllers c, stk
         
     | 
| 
      
 264 
     | 
    
         
            +
                  end.compact.flatten
         
     | 
| 
       280 
265 
     | 
    
         
             
                end
         
     | 
| 
       281 
266 
     | 
    
         | 
| 
       282 
     | 
    
         
            -
                 
     | 
| 
       283 
     | 
    
         
            -
                 
     | 
| 
       284 
     | 
    
         
            -
             
     | 
| 
       285 
     | 
    
         
            -
             
     | 
| 
       286 
     | 
    
         
            -
             
     | 
| 
       287 
     | 
    
         
            -
             
     | 
| 
       288 
     | 
    
         
            -
             
     | 
| 
       289 
     | 
    
         
            -
             
     | 
| 
       290 
     | 
    
         
            -
             
     | 
| 
       291 
     | 
    
         
            -
             
     | 
| 
      
 267 
     | 
    
         
            +
                ##
         
     | 
| 
      
 268 
     | 
    
         
            +
                # Family is important.
         
     | 
| 
      
 269 
     | 
    
         
            +
                #
         
     | 
| 
      
 270 
     | 
    
         
            +
                # Sets up a new Maveric with everything it needs for normal
         
     | 
| 
      
 271 
     | 
    
         
            +
                # operation. Many things are either copied or included from it's
         
     | 
| 
      
 272 
     | 
    
         
            +
                # parent The logger is copied and Models and Views are included by
         
     | 
| 
      
 273 
     | 
    
         
            +
                # their respective modules.
         
     | 
| 
      
 274 
     | 
    
         
            +
                def inherited klass
         
     | 
| 
      
 275 
     | 
    
         
            +
                  ::Maveric.log.info "#{klass} inherits from #{self}."
         
     | 
| 
      
 276 
     | 
    
         
            +
                  super klass
         
     | 
| 
      
 277 
     | 
    
         
            +
                  parent = self
         
     | 
| 
      
 278 
     | 
    
         
            +
                  klass.class_eval do
         
     | 
| 
      
 279 
     | 
    
         
            +
                    const_set(:Models, Module.new).
         
     | 
| 
      
 280 
     | 
    
         
            +
                      module_eval { include parent::Models }
         
     | 
| 
      
 281 
     | 
    
         
            +
                    const_set(:Views, Module.new).
         
     | 
| 
      
 282 
     | 
    
         
            +
                      module_eval { include parent::Views }
         
     | 
| 
       292 
283 
     | 
    
         
             
                  end
         
     | 
| 
       293 
284 
     | 
    
         
             
                end
         
     | 
| 
       294 
285 
     | 
    
         
             
              end
         
     | 
| 
       295 
286 
     | 
    
         | 
| 
       296 
     | 
    
         
            -
              attr_reader :routings, :sessions
         
     | 
| 
       297 
     | 
    
         
            -
              def log; self.class.log; end
         
     | 
| 
       298 
     | 
    
         
            -
             
     | 
| 
       299 
287 
     | 
    
         
             
              ##
         
     | 
| 
       300 
     | 
    
         
            -
              #  
     | 
| 
       301 
     | 
    
         
            -
              #  
     | 
| 
       302 
     | 
    
         
            -
              def  
     | 
| 
       303 
     | 
    
         
            -
                log.info "#{self} 
     | 
| 
       304 
     | 
    
         
            -
                 
     | 
| 
       305 
     | 
    
         
            -
                @ 
     | 
| 
      
 288 
     | 
    
         
            +
              # When instantiated, the Maveric look search through its constants for
         
     | 
| 
      
 289 
     | 
    
         
            +
              # nested Controllers and adds them by their roots. 
         
     | 
| 
      
 290 
     | 
    
         
            +
              def initialize opts={}
         
     | 
| 
      
 291 
     | 
    
         
            +
                ::Maveric.log.info "#{self.class} instantiated at #{Time.now}"
         
     | 
| 
      
 292 
     | 
    
         
            +
                ::Maveric.type_check :opts, opts, Hash
         
     | 
| 
      
 293 
     | 
    
         
            +
                @options = opts
         
     | 
| 
      
 294 
     | 
    
         
            +
                @routings = Hash.new # should be an associative array or ordered hash.
         
     | 
| 
      
 295 
     | 
    
         
            +
                self.class.nested_controllers.
         
     | 
| 
      
 296 
     | 
    
         
            +
                  each {|c| add_routes c, c.routes, {:maveric => self} }
         
     | 
| 
       306 
297 
     | 
    
         
             
              end
         
     | 
| 
       307 
298 
     | 
    
         | 
| 
       308 
     | 
    
         
            -
               
     | 
| 
       309 
     | 
    
         
            -
              def add_routes c, *r
         
     | 
| 
       310 
     | 
    
         
            -
                r.flatten.map {|route| add_route c, route }
         
     | 
| 
       311 
     | 
    
         
            -
              end
         
     | 
| 
      
 299 
     | 
    
         
            +
              attr_reader :options, :routings
         
     | 
| 
       312 
300 
     | 
    
         | 
| 
       313 
     | 
    
         
            -
              ##
         
     | 
| 
       314 
     | 
    
         
            -
               
     | 
| 
       315 
     | 
    
         
            -
             
     | 
| 
       316 
     | 
    
         
            -
              def set_routes c, *r
         
     | 
| 
       317 
     | 
    
         
            -
                log.info "#{self}#set_route #{c} #{r.inspect}"
         
     | 
| 
       318 
     | 
    
         
            -
                @routings.delete_if{|e| e.run == c }
         
     | 
| 
       319 
     | 
    
         
            -
                add_routes c, *r
         
     | 
| 
      
 301 
     | 
    
         
            +
              ## Returns an array of controllers that are being routed to.
         
     | 
| 
      
 302 
     | 
    
         
            +
              def controllers
         
     | 
| 
      
 303 
     | 
    
         
            +
                @routings.values.uniq
         
     | 
| 
       320 
304 
     | 
    
         
             
              end
         
     | 
| 
       321 
305 
     | 
    
         | 
| 
       322 
306 
     | 
    
         
             
              ##
         
     | 
| 
       323 
     | 
    
         
            -
              #  
     | 
| 
       324 
     | 
    
         
            -
              #
         
     | 
| 
       325 
     | 
    
         
            -
               
     | 
| 
       326 
     | 
    
         
            -
             
     | 
| 
       327 
     | 
    
         
            -
             
     | 
| 
       328 
     | 
    
         
            -
             
     | 
| 
       329 
     | 
    
         
            -
             
     | 
| 
       330 
     | 
    
         
            -
             
     | 
| 
       331 
     | 
    
         
            -
                 
     | 
| 
       332 
     | 
    
         
            -
             
     | 
| 
       333 
     | 
    
         
            -
                env[:maveric] = self
         
     | 
| 
       334 
     | 
    
         
            -
             
     | 
| 
       335 
     | 
    
         
            -
                # determines the appropriate route and build the route info.
         
     | 
| 
       336 
     | 
    
         
            -
                url = Maveric.unescape env['REQUEST_URI']
         
     | 
| 
       337 
     | 
    
         
            -
                route, rinfo = routings.
         
     | 
| 
       338 
     | 
    
         
            -
                  find {|r| o = r.match_url(url) and break [r, o] }
         
     | 
| 
       339 
     | 
    
         
            -
                env.update :route => route, :route_info => rinfo
         
     | 
| 
       340 
     | 
    
         
            -
                #::Maveric.log.warn env.map{|k,v|"#{k}: #{v.inspect}"}*"\n"
         
     | 
| 
       341 
     | 
    
         
            -
             
     | 
| 
       342 
     | 
    
         
            -
                # determine if there's a multipart boundary
         
     | 
| 
       343 
     | 
    
         
            -
                if env['REQUEST_METHOD'] =~ /^post$/i \
         
     | 
| 
       344 
     | 
    
         
            -
                  and env['CONTENT_TYPE'] =~ MP_BOUND_REGEX
         
     | 
| 
       345 
     | 
    
         
            -
                  env[:multipart_boundary] = $1
         
     | 
| 
       346 
     | 
    
         
            -
                end
         
     | 
| 
      
 307 
     | 
    
         
            +
              # Places a route to a controller. Will generate a new Routing if route is a
         
     | 
| 
      
 308 
     | 
    
         
            +
              # String.
         
     | 
| 
      
 309 
     | 
    
         
            +
              def add_route controller, route, opts={}
         
     | 
| 
      
 310 
     | 
    
         
            +
                ::Maveric.log.info "#{self.class}#add_route"+
         
     | 
| 
      
 311 
     | 
    
         
            +
                  " #{controller.inspect} #{route.inspect}"
         
     | 
| 
      
 312 
     | 
    
         
            +
                route = ::Maveric::Routing.new route, opts if route.instance_of? String
         
     | 
| 
      
 313 
     | 
    
         
            +
                ::Maveric.type_check :controller, controller, Class
         
     | 
| 
      
 314 
     | 
    
         
            +
                ::Maveric.type_check :route, route, ::Maveric::Routing
         
     | 
| 
      
 315 
     | 
    
         
            +
                @routings[route] = controller
         
     | 
| 
      
 316 
     | 
    
         
            +
              end
         
     | 
| 
       347 
317 
     | 
    
         | 
| 
       348 
     | 
    
         
            -
             
     | 
| 
       349 
     | 
    
         
            -
             
     | 
| 
       350 
     | 
    
         
            -
                 
     | 
| 
       351 
     | 
    
         
            -
                session_id = session_id[0] if session_id.is_a? Array
         
     | 
| 
       352 
     | 
    
         
            -
                env[:session] = sessions[ session_id ]
         
     | 
| 
       353 
     | 
    
         
            -
                env
         
     | 
| 
      
 318 
     | 
    
         
            +
              ## Used for adding multiple routes via #add_route
         
     | 
| 
      
 319 
     | 
    
         
            +
              def add_routes controller, routes, opts={}
         
     | 
| 
      
 320 
     | 
    
         
            +
                routes.flatten.map {|route| add_route controller, route, opts }
         
     | 
| 
       354 
321 
     | 
    
         
             
              end
         
     | 
| 
       355 
322 
     | 
    
         | 
| 
       356 
323 
     | 
    
         
             
              ##
         
     | 
| 
       357 
324 
     | 
    
         
             
              # A Maveric's cue to start doing the heavy lifting. The env should be
         
     | 
| 
       358 
325 
     | 
    
         
             
              # a hash with the typical assignments from an HTTP environment or crying
         
     | 
| 
       359 
     | 
    
         
            -
              # and whining will ensue. The req_body argument should be a  
     | 
| 
       360 
     | 
    
         
            -
              #  
     | 
| 
       361 
     | 
    
         
            -
              def  
     | 
| 
       362 
     | 
    
         
            -
                log.info "#{self.class}# 
     | 
| 
      
 326 
     | 
    
         
            +
              # and whining will ensue. The req_body argument should be a StringIO.
         
     | 
| 
      
 327 
     | 
    
         
            +
              # TODO: More doc! :P
         
     | 
| 
      
 328 
     | 
    
         
            +
              def process req_body=$stdin, env=ENV, opts={}
         
     | 
| 
      
 329 
     | 
    
         
            +
                ::Maveric.log.info "#{self.class}#process\n  "+
         
     | 
| 
       363 
330 
     | 
    
         
             
                  "[#{Time.now}] #{env['REMOTE_ADDR']} => #{env['REQUEST_URI']}"
         
     | 
| 
       364 
     | 
    
         
            -
                ::Maveric.type_check :req_body, req_body,  
     | 
| 
      
 331 
     | 
    
         
            +
                ::Maveric.type_check :req_body, req_body, StringIO
         
     | 
| 
       365 
332 
     | 
    
         
             
                ::Maveric.type_check :env, env, Hash
         
     | 
| 
       366 
     | 
    
         
            -
                 
     | 
| 
       367 
     | 
    
         
            -
             
     | 
| 
       368 
     | 
    
         
            -
                   
     | 
| 
       369 
     | 
    
         
            -
             
     | 
| 
       370 
     | 
    
         
            -
             
     | 
| 
       371 
     | 
    
         
            -
             
     | 
| 
       372 
     | 
    
         
            -
             
     | 
| 
       373 
     | 
    
         
            -
                       
     | 
| 
       374 
     | 
    
         
            -
                        parse_multipart(env[:multipart_boundary], req_body) :
         
     | 
| 
       375 
     | 
    
         
            -
                        Maveric.query_parse(req_body.read)
         
     | 
| 
       376 
     | 
    
         
            -
                      env[:params].update qparams
         
     | 
| 
       377 
     | 
    
         
            -
                    end
         
     | 
| 
       378 
     | 
    
         
            -
             
     | 
| 
       379 
     | 
    
         
            -
                    env[:route].run[req_body, env, *opts]
         
     | 
| 
       380 
     | 
    
         
            -
                  rescue ServerError then $!
         
     | 
| 
       381 
     | 
    
         
            -
                  rescue 
         
     | 
| 
       382 
     | 
    
         
            -
                    log.fatal "#{Time.now}: #{$!.to_s}\n#{$!.backtrace*"\n"}"
         
     | 
| 
       383 
     | 
    
         
            -
                    # have a nice fail, then have a hard fail if something fails there.
         
     | 
| 
       384 
     | 
    
         
            -
                    begin
         
     | 
| 
       385 
     | 
    
         
            -
                      ServerError.new($!)
         
     | 
| 
       386 
     | 
    
         
            -
                    end
         
     | 
| 
      
 333 
     | 
    
         
            +
                begin
         
     | 
| 
      
 334 
     | 
    
         
            +
                  prepare_environment env unless env.key? :maveric
         
     | 
| 
      
 335 
     | 
    
         
            +
                  raise RuntimeError, [404, "Page not found."] unless env[:route]
         
     | 
| 
      
 336 
     | 
    
         
            +
             
     | 
| 
      
 337 
     | 
    
         
            +
                  if env['REQUEST_METHOD'] =~ /^post$/i
         
     | 
| 
      
 338 
     | 
    
         
            +
                    env[:params].update env.key?(:multipart_boundary) ?
         
     | 
| 
      
 339 
     | 
    
         
            +
                      parse_multipart(env[:multipart_boundary], req_body) :
         
     | 
| 
      
 340 
     | 
    
         
            +
                      ::Maveric.query_parse(req_body.read)
         
     | 
| 
       387 
341 
     | 
    
         
             
                  end
         
     | 
| 
       388 
     | 
    
         
            -
                end
         
     | 
| 
       389 
     | 
    
         
            -
                log.info "#{self.class}#dispatch #{id}\n#{n}".chomp
         
     | 
| 
       390 
     | 
    
         
            -
                response
         
     | 
| 
       391 
     | 
    
         
            -
              end
         
     | 
| 
       392 
     | 
    
         
            -
            end
         
     | 
| 
       393 
342 
     | 
    
         | 
| 
       394 
     | 
    
         
            -
             
     | 
| 
       395 
     | 
    
         
            -
             
     | 
| 
       396 
     | 
    
         
            -
             
     | 
| 
       397 
     | 
    
         
            -
             
     | 
| 
       398 
     | 
    
         
            -
             
     | 
| 
       399 
     | 
    
         
            -
             
     | 
| 
       400 
     | 
    
         
            -
             
     | 
| 
       401 
     | 
    
         
            -
             
     | 
| 
       402 
     | 
    
         
            -
             
     | 
| 
       403 
     | 
    
         
            -
             
     | 
| 
       404 
     | 
    
         
            -
                #  
     | 
| 
       405 
     | 
    
         
            -
             
     | 
| 
       406 
     | 
    
         
            -
                   
     | 
| 
       407 
     | 
    
         
            -
             
     | 
| 
       408 
     | 
    
         
            -
             
     | 
| 
       409 
     | 
    
         
            -
             
     | 
| 
       410 
     | 
    
         
            -
             
     | 
| 
       411 
     | 
    
         
            -
             
     | 
| 
       412 
     | 
    
         
            -
             
     | 
| 
       413 
     | 
    
         
            -
              # and simple way to generate fast HTTP response error thingies. As long as
         
     | 
| 
       414 
     | 
    
         
            -
              # you're within a call to dispatch (with no further rescue clauses) the
         
     | 
| 
       415 
     | 
    
         
            -
              # ServerError will propogate up and be returned. As a ServerError has similar
         
     | 
| 
       416 
     | 
    
         
            -
              # accessors as a Controller, they should be compatible with any outputting
         
     | 
| 
       417 
     | 
    
         
            -
              # implimentation.
         
     | 
| 
       418 
     | 
    
         
            -
              #
         
     | 
| 
       419 
     | 
    
         
            -
              # If the status code is 5xx (500 by default) then a backtrace is appended to
         
     | 
| 
       420 
     | 
    
         
            -
              # the response body.
         
     | 
| 
       421 
     | 
    
         
            -
              #
         
     | 
| 
       422 
     | 
    
         
            -
              #   raise ServerErrpr; # 500 error
         
     | 
| 
       423 
     | 
    
         
            -
              #   raise ServerError, 'Crap!'; # 500 error with message set to 'Crap!'
         
     | 
| 
       424 
     | 
    
         
            -
              #   raise ServerError, $!; # 500 error with same message and backtrace as
         
     | 
| 
       425 
     | 
    
         
            -
              #     # $! with a note in the message as to  the original exception class
         
     | 
| 
       426 
     | 
    
         
            -
              #   raise ServerError, [status, headers, body, *other_data] # Magic!
         
     | 
| 
       427 
     | 
    
         
            -
              #
         
     | 
| 
       428 
     | 
    
         
            -
              # In the final example line an Array is passed to raise as a second argument
         
     | 
| 
       429 
     | 
    
         
            -
              # rather than a String. This only works as intended if the first element is
         
     | 
| 
       430 
     | 
    
         
            -
              # an Integer. This is taken as the HTTP status code. The next element is
         
     | 
| 
       431 
     | 
    
         
            -
              # tested to be a Hash, if so then it's values are merged into the HTTP
         
     | 
| 
       432 
     | 
    
         
            -
              # headers. Then next item is tested to be a String, if so it is appended to
         
     | 
| 
       433 
     | 
    
         
            -
              # the response body. All remaining elements are appended to the response
         
     | 
| 
       434 
     | 
    
         
            -
              # body in inspect format.
         
     | 
| 
       435 
     | 
    
         
            -
              def initialize data=nil
         
     | 
| 
       436 
     | 
    
         
            -
                @status, @headers, @body = 500, {'Content-Type'=>'text/plain'}, ''
         
     | 
| 
       437 
     | 
    
         
            -
                case msg = data
         
     | 
| 
       438 
     | 
    
         
            -
                when Exception
         
     | 
| 
       439 
     | 
    
         
            -
                  msg = @body << data.class.to_s+" "+data.message
         
     | 
| 
       440 
     | 
    
         
            -
                  set_backtrace data.backtrace
         
     | 
| 
       441 
     | 
    
         
            -
                  @body << "\n\n"+data.backtrace*"\n"
         
     | 
| 
       442 
     | 
    
         
            -
                when String
         
     | 
| 
       443 
     | 
    
         
            -
                  @body << msg
         
     | 
| 
       444 
     | 
    
         
            -
                when Array
         
     | 
| 
       445 
     | 
    
         
            -
                  if data[0].is_a? Integer
         
     | 
| 
       446 
     | 
    
         
            -
                    # [status, headers, body, request]
         
     | 
| 
       447 
     | 
    
         
            -
                    @status = data.shift
         
     | 
| 
       448 
     | 
    
         
            -
                    @headers.update data.shift if data.first.is_a? Hash
         
     | 
| 
       449 
     | 
    
         
            -
                    @body.concat data.shift if data.first.is_a? String
         
     | 
| 
       450 
     | 
    
         
            -
                    msg = @body.dup
         
     | 
| 
       451 
     | 
    
         
            -
                    @body << "\n\n#{data.map{|e|e.inspect}*"\n"}" unless data.empty?
         
     | 
| 
      
 343 
     | 
    
         
            +
                  if (controller = env[:route][:controller]) < ::Maveric::Controller
         
     | 
| 
      
 344 
     | 
    
         
            +
                    controller.new req_body, env, opts
         
     | 
| 
      
 345 
     | 
    
         
            +
                  elsif controller.is_a? String
         
     | 
| 
      
 346 
     | 
    
         
            +
                    ::Maveric.log.warn "We have not implemented dynamic route dispatch "+
         
     | 
| 
      
 347 
     | 
    
         
            +
                      "just yet. Please explicitly state :controller."
         
     | 
| 
      
 348 
     | 
    
         
            +
                    raise "Dynamic dispatching failed."
         
     | 
| 
      
 349 
     | 
    
         
            +
                  else
         
     | 
| 
      
 350 
     | 
    
         
            +
                    raise TypeError, "Lapse in handling. Something fugly got dropped."+
         
     | 
| 
      
 351 
     | 
    
         
            +
                      " Notify Maveric coder please."
         
     | 
| 
      
 352 
     | 
    
         
            +
                  end
         
     | 
| 
      
 353 
     | 
    
         
            +
                rescue # we catch exception.is_a? StandardError
         
     | 
| 
      
 354 
     | 
    
         
            +
                  ::Maveric.log.error "#{Time.now}:\n#{$!.inspect}\n#{$!.backtrace*"\n"}"
         
     | 
| 
      
 355 
     | 
    
         
            +
                  begin
         
     | 
| 
      
 356 
     | 
    
         
            +
                    raise $! # this makes sense in a certain context...
         
     | 
| 
      
 357 
     | 
    
         
            +
                    # Here is where we should have transformational stuffs for accessorizing
         
     | 
| 
      
 358 
     | 
    
         
            +
                    # or customizing error pages. As long as someone doesn't get stupid 
         
     | 
| 
      
 359 
     | 
    
         
            +
                    # about it.
         
     | 
| 
      
 360 
     | 
    
         
            +
                  rescue
         
     | 
| 
      
 361 
     | 
    
         
            +
                    return $!
         
     | 
| 
       452 
362 
     | 
    
         
             
                  end
         
     | 
| 
       453 
363 
     | 
    
         
             
                end
         
     | 
| 
       454 
     | 
    
         
            -
                if @status/100%10 == 5
         
     | 
| 
       455 
     | 
    
         
            -
                  @body << "\n\n#{$!}\n#{$@[0..10]*"\n"}"
         
     | 
| 
       456 
     | 
    
         
            -
                end
         
     | 
| 
       457 
     | 
    
         
            -
                super msg
         
     | 
| 
       458 
     | 
    
         
            -
              end
         
     | 
| 
       459 
     | 
    
         
            -
              attr_reader :status, :headers, :body
         
     | 
| 
       460 
     | 
    
         
            -
             
     | 
| 
       461 
     | 
    
         
            -
              ## Allows fun with splat (*).
         
     | 
| 
       462 
     | 
    
         
            -
              def to_a
         
     | 
| 
       463 
     | 
    
         
            -
                [
         
     | 
| 
       464 
     | 
    
         
            -
                  (@status.dup.freeze rescue @status), 
         
     | 
| 
       465 
     | 
    
         
            -
                  @headers.dup.freeze, 
         
     | 
| 
       466 
     | 
    
         
            -
                  @body.dup.freeze, 
         
     | 
| 
       467 
     | 
    
         
            -
                  (@env.dup.freeze rescue @env)
         
     | 
| 
       468 
     | 
    
         
            -
                ].freeze
         
     | 
| 
       469 
     | 
    
         
            -
              end
         
     | 
| 
       470 
     | 
    
         
            -
             
     | 
| 
       471 
     | 
    
         
            -
              ## Fun with raw output!
         
     | 
| 
       472 
     | 
    
         
            -
              def to_s
         
     | 
| 
       473 
     | 
    
         
            -
                status, headers, body, e, i = to_a
         
     | 
| 
       474 
     | 
    
         
            -
                response = "Status: #{status}"+Maveric::EOL
         
     | 
| 
       475 
     | 
    
         
            -
                response << headers.map{|(k,v)| "#{k}: #{v}" }*Maveric::EOL
         
     | 
| 
       476 
     | 
    
         
            -
                response << Maveric::EOL*2
         
     | 
| 
       477 
     | 
    
         
            -
                response << body
         
     | 
| 
       478 
     | 
    
         
            -
              end
         
     | 
| 
       479 
     | 
    
         
            -
            end
         
     | 
| 
       480 
     | 
    
         
            -
             
     | 
| 
       481 
     | 
    
         
            -
            ##
         
     | 
| 
       482 
     | 
    
         
            -
            # Contains session data and provides conveniance in generating an appropriate
         
     | 
| 
       483 
     | 
    
         
            -
            # cookie.
         
     | 
| 
       484 
     | 
    
         
            -
            class Maveric::Session
         
     | 
| 
       485 
     | 
    
         
            -
              COOKIE_NAME = 'SESSIONID'
         
     | 
| 
       486 
     | 
    
         
            -
              DURATION = 15*60
         
     | 
| 
       487 
     | 
    
         
            -
              KEY_GRADE = 16
         
     | 
| 
       488 
     | 
    
         
            -
              KEY_LENGTH = 16
         
     | 
| 
       489 
     | 
    
         
            -
             
     | 
| 
       490 
     | 
    
         
            -
              ## Do you want to alter the duration of sessions? M'kay.
         
     | 
| 
       491 
     | 
    
         
            -
              def initialize duration=DURATION
         
     | 
| 
       492 
     | 
    
         
            -
                @id = Array.new(KEY_LENGTH){rand(KEY_GRADE).to_s(KEY_GRADE)}*''
         
     | 
| 
       493 
     | 
    
         
            -
                @duration, @data = duration, {}
         
     | 
| 
       494 
     | 
    
         
            -
                Maveric.log.debug self
         
     | 
| 
       495 
364 
     | 
    
         
             
              end
         
     | 
| 
       496 
     | 
    
         
            -
              attr_reader :id, :expires, :duration, :data
         
     | 
| 
       497 
     | 
    
         
            -
              attr_writer :duration
         
     | 
| 
       498 
365 
     | 
    
         | 
| 
       499 
366 
     | 
    
         
             
              ##
         
     | 
| 
       500 
     | 
    
         
            -
              #  
     | 
| 
       501 
     | 
    
         
            -
              #  
     | 
| 
       502 
     | 
    
         
            -
              #
         
     | 
| 
       503 
     | 
    
         
            -
              #  
     | 
| 
       504 
     | 
    
         
            -
              #  
     | 
| 
       505 
     | 
    
         
            -
               
     | 
| 
       506 
     | 
    
         
            -
             
     | 
| 
       507 
     | 
    
         
            -
             
     | 
| 
       508 
     | 
    
         
            -
                 
     | 
| 
      
 367 
     | 
    
         
            +
              # The env argument should be a normal environment hash derived from HTTP.
         
     | 
| 
      
 368 
     | 
    
         
            +
              # Runs through a list of sorted methods, looking for methods beginning with
         
     | 
| 
      
 369 
     | 
    
         
            +
              # 'env_' followed by a number followed by a '_' and then whatever descriptive
         
     | 
| 
      
 370 
     | 
    
         
            +
              # ending the programmer gives the method. It passes the env hash to those
         
     | 
| 
      
 371 
     | 
    
         
            +
              # methods for them to update and mess around with the env in appropriate
         
     | 
| 
      
 372 
     | 
    
         
            +
              # ways. See default/included methods for example usage.
         
     | 
| 
      
 373 
     | 
    
         
            +
              # NOTE: Override the defaults at your own risk!
         
     | 
| 
      
 374 
     | 
    
         
            +
              def prepare_environment env
         
     | 
| 
      
 375 
     | 
    
         
            +
                ::Maveric.type_check :env, env, Hash
         
     | 
| 
      
 376 
     | 
    
         
            +
                env.update :maveric => self
         
     | 
| 
      
 377 
     | 
    
         
            +
                methods.sort.each{|m| __send__ m, env if /^env_\d+_/=~m }
         
     | 
| 
       509 
378 
     | 
    
         
             
              end
         
     | 
| 
       510 
379 
     | 
    
         | 
| 
       511 
     | 
    
         
            -
              ##
         
     | 
| 
       512 
     | 
    
         
            -
               
     | 
| 
       513 
     | 
    
         
            -
             
     | 
| 
       514 
     | 
    
         
            -
              def to_s env=Hash.new{|h,k|"#{k} not defined"}
         
     | 
| 
       515 
     | 
    
         
            -
                touch unless @expires
         
     | 
| 
       516 
     | 
    
         
            -
                c = "#{COOKIE_NAME}=#{id};" #required
         
     | 
| 
       517 
     | 
    
         
            -
                c << " expires=#{@expires.httpdate}" if @expires
         
     | 
| 
       518 
     | 
    
         
            -
                c << " path=#{env['SCRIPT_NAME']};"
         
     | 
| 
       519 
     | 
    
         
            -
                c << " domain=#{env['SERVER_NAME']};"
         
     | 
| 
       520 
     | 
    
         
            -
                c << " secure" if false
         
     | 
| 
       521 
     | 
    
         
            -
                c
         
     | 
| 
      
 380 
     | 
    
         
            +
              ## Cookies!
         
     | 
| 
      
 381 
     | 
    
         
            +
              def env_0_cookies env
         
     | 
| 
      
 382 
     | 
    
         
            +
                env[:cookies] = ::Maveric.query_parse env['HTTP_COOKIE'], ';,'
         
     | 
| 
       522 
383 
     | 
    
         
             
              end
         
     | 
| 
       523 
     | 
    
         
            -
             
     | 
| 
       524 
     | 
    
         
            -
             
     | 
| 
       525 
     | 
    
         
            -
             
     | 
| 
       526 
     | 
    
         
            -
             
     | 
| 
       527 
     | 
    
         
            -
             
     | 
| 
       528 
     | 
    
         
            -
             
     | 
| 
       529 
     | 
    
         
            -
             
     | 
| 
       530 
     | 
    
         
            -
             
     | 
| 
       531 
     | 
    
         
            -
             
     | 
| 
       532 
     | 
    
         
            -
             
     | 
| 
       533 
     | 
    
         
            -
              ## Seperator characters.
         
     | 
| 
       534 
     | 
    
         
            -
              URI_CHAR = '[^/?:,&#]'
         
     | 
| 
       535 
     | 
    
         
            -
             
     | 
| 
       536 
     | 
    
         
            -
              ##
         
     | 
| 
       537 
     | 
    
         
            -
              # Create a Route from the String route where varying parts of the url are
         
     | 
| 
       538 
     | 
    
         
            -
              # represented as Symbol like sigils. The run argument should be a Proc or
         
     | 
| 
       539 
     | 
    
         
            -
              # a Maveric::Controller subclass.
         
     | 
| 
       540 
     | 
    
         
            -
              #   Route.new '/:page', proc{|request| p request.params[:params][:page] }
         
     | 
| 
       541 
     | 
    
         
            -
              #   Route.new '/:page', MyController # MyController < Maveric::Controller
         
     | 
| 
       542 
     | 
    
         
            -
              def initialize route, run
         
     | 
| 
       543 
     | 
    
         
            -
                ::Maveric.type_check :route, route, String
         
     | 
| 
       544 
     | 
    
         
            -
                ::Maveric.type_check :run, run, Proc, ::Maveric::Controller do |k|
         
     | 
| 
       545 
     | 
    
         
            -
                  k < ::Maveric::Controller
         
     | 
| 
      
 384 
     | 
    
         
            +
              ## Params!
         
     | 
| 
      
 385 
     | 
    
         
            +
              def env_0_params env
         
     | 
| 
      
 386 
     | 
    
         
            +
                env[:params]  = ::Maveric.query_parse env['QUERY_STRING']
         
     | 
| 
      
 387 
     | 
    
         
            +
              end
         
     | 
| 
      
 388 
     | 
    
         
            +
              ## More Params!?
         
     | 
| 
      
 389 
     | 
    
         
            +
              def env_0_multipart_detect env
         
     | 
| 
      
 390 
     | 
    
         
            +
                if not env.key? :multipart_boundary \
         
     | 
| 
      
 391 
     | 
    
         
            +
                  and env['REQUEST_METHOD'] =~ /^post$/i \
         
     | 
| 
      
 392 
     | 
    
         
            +
                  and env['CONTENT_TYPE'] =~ MP_BOUND_REGEX
         
     | 
| 
      
 393 
     | 
    
         
            +
                  env[:multipart_boundary] = $1
         
     | 
| 
       546 
394 
     | 
    
         
             
                end
         
     | 
| 
       547 
     | 
    
         
            -
                @run = run
         
     | 
| 
       548 
     | 
    
         
            -
                @route = route.gsub /\/+/, '/'
         
     | 
| 
       549 
     | 
    
         
            -
                @params = []
         
     | 
| 
       550 
     | 
    
         
            -
                @regex = Regexp.new '^'+@route.gsub(/\/:(#{URI_CHAR}+)/){
         
     | 
| 
       551 
     | 
    
         
            -
                  @params << $1.to_sym
         
     | 
| 
       552 
     | 
    
         
            -
                  raise 'Duplicated parameters.' unless @params.uniq.size == @params.size
         
     | 
| 
       553 
     | 
    
         
            -
                  "/(#{URI_CHAR}+)"
         
     | 
| 
       554 
     | 
    
         
            -
                }+'$'
         
     | 
| 
       555 
     | 
    
         
            -
                Maveric.log.debug self
         
     | 
| 
       556 
395 
     | 
    
         
             
              end
         
     | 
| 
       557 
     | 
    
         
            -
               
     | 
| 
       558 
     | 
    
         
            -
             
     | 
| 
       559 
     | 
    
         
            -
             
     | 
| 
       560 
     | 
    
         
            -
             
     | 
| 
       561 
     | 
    
         
            -
             
     | 
| 
       562 
     | 
    
         
            -
             
     | 
| 
       563 
     | 
    
         
            -
              # Hash.
         
     | 
| 
       564 
     | 
    
         
            -
              def build_url hsh
         
     | 
| 
       565 
     | 
    
         
            -
                Maveric.log.debug "#{self.class}#build_url"+
         
     | 
| 
       566 
     | 
    
         
            -
                  " #{hsh.inspect} : #{self.inspect}"
         
     | 
| 
       567 
     | 
    
         
            -
                #@params.inject(@route){|r,k| r.gsub(/#{k.inspect}/, hsh[k]) }
         
     | 
| 
       568 
     | 
    
         
            -
                hsh.inject(@route){|r,(k,v)| r.gsub(/:#{k}/, v.to_s) }
         
     | 
| 
      
 396 
     | 
    
         
            +
              ## What am I doing in this basket...
         
     | 
| 
      
 397 
     | 
    
         
            +
              def env_0_route env
         
     | 
| 
      
 398 
     | 
    
         
            +
                url = ::Maveric.unescape env['REQUEST_URI']
         
     | 
| 
      
 399 
     | 
    
         
            +
                env[:route] = routings.eject do |(r,c)|
         
     | 
| 
      
 400 
     | 
    
         
            +
                  b=r.route(url) and {:controller=>c}.update b
         
     | 
| 
      
 401 
     | 
    
         
            +
                end
         
     | 
| 
       569 
402 
     | 
    
         
             
              end
         
     | 
| 
       570 
403 
     | 
    
         | 
| 
       571 
     | 
    
         
            -
              ##
         
     | 
| 
       572 
     | 
    
         
            -
               
     | 
| 
       573 
     | 
    
         
            -
             
     | 
| 
       574 
     | 
    
         
            -
             
     | 
| 
       575 
     | 
    
         
            -
             
     | 
| 
       576 
     | 
    
         
            -
             
     | 
| 
       577 
     | 
    
         
            -
                return nil unless md = @regex.match(url)
         
     | 
| 
       578 
     | 
    
         
            -
                Hash[ *@params.zip(md.captures).flatten ]
         
     | 
| 
      
 404 
     | 
    
         
            +
              ## Holds views related methods and helpers
         
     | 
| 
      
 405 
     | 
    
         
            +
              module Views
         
     | 
| 
      
 406 
     | 
    
         
            +
                def path_to c, a={}
         
     | 
| 
      
 407 
     | 
    
         
            +
                  ::Maveric.log.info "#{self.class}#path_to #{c} #{a.inspect}"
         
     | 
| 
      
 408 
     | 
    
         
            +
                  @env[:maveric].routings.eject{|(r,d)| r.build a if d == c }
         
     | 
| 
      
 409 
     | 
    
         
            +
                end
         
     | 
| 
       579 
410 
     | 
    
         
             
              end
         
     | 
| 
       580 
411 
     | 
    
         | 
| 
       581 
     | 
    
         
            -
              ##
         
     | 
| 
       582 
     | 
    
         
            -
               
     | 
| 
       583 
     | 
    
         
            -
              # well as subclasses of Maveric::Controller.
         
     | 
| 
       584 
     | 
    
         
            -
              def === arg
         
     | 
| 
       585 
     | 
    
         
            -
                Maveric.log.debug "#{self.class}#==="+
         
     | 
| 
       586 
     | 
    
         
            -
                  " #{arg.inspect} : #{self.inspect}"
         
     | 
| 
       587 
     | 
    
         
            -
                case arg
         
     | 
| 
       588 
     | 
    
         
            -
                when Array  then arg.size == @params.size and \
         
     | 
| 
       589 
     | 
    
         
            -
                  not arg.any?{|v|!@params.include?(v)}
         
     | 
| 
       590 
     | 
    
         
            -
                when Hash   then self === arg.keys
         
     | 
| 
       591 
     | 
    
         
            -
                when String then @regex.match(arg).nil?
         
     | 
| 
       592 
     | 
    
         
            -
                when Proc   then @run == arg
         
     | 
| 
       593 
     | 
    
         
            -
                when Class  then @run == arg if arg < Maveric::Controller
         
     | 
| 
       594 
     | 
    
         
            -
                end
         
     | 
| 
      
 412 
     | 
    
         
            +
              ## Repository for models. Still not realy utilized.
         
     | 
| 
      
 413 
     | 
    
         
            +
              module Models
         
     | 
| 
       595 
414 
     | 
    
         
             
              end
         
     | 
| 
       596 
415 
     | 
    
         
             
            end
         
     | 
| 
       597 
416 
     | 
    
         | 
| 
       598 
417 
     | 
    
         
             
            ##
         
     | 
| 
       599 
     | 
    
         
            -
            #  
     | 
| 
       600 
     | 
    
         
            -
            #  
     | 
| 
       601 
     | 
    
         
            -
            # 
         
     | 
| 
       602 
     | 
    
         
            -
            # 
     | 
| 
       603 
     | 
    
         
            -
            #  
     | 
| 
       604 
     | 
    
         
            -
            #  
     | 
| 
       605 
     | 
    
         
            -
            #  
     | 
| 
       606 
     | 
    
         
            -
            #  
     | 
| 
       607 
     | 
    
         
            -
            #  
     | 
| 
       608 
     | 
    
         
            -
            # 
         
     | 
| 
       609 
     | 
    
         
            -
            # If the methods get, post, put, or delete are called (typically called in
         
     | 
| 
       610 
     | 
    
         
            -
            # Controller.new when setting the body of the response) and they haven't been
         
     | 
| 
       611 
     | 
    
         
            -
            # defined then a ServerError is thrown with a status of 503.
         
     | 
| 
       612 
     | 
    
         
            -
            # 
         
     | 
| 
       613 
     | 
    
         
            -
            # * Access to the raw request is provided through @request.
         
     | 
| 
       614 
     | 
    
         
            -
            # * Cookies are reflected in @cookies, alterations will be passed to the 
         
     | 
| 
       615 
     | 
    
         
            -
            #   client response.
         
     | 
| 
       616 
     | 
    
         
            -
            #   * Alteration of the session id cookie is not recommended.
         
     | 
| 
       617 
     | 
    
         
            -
            # * HTTP headers should be set in @headers. The HTTP status should be set 
         
     | 
| 
       618 
     | 
    
         
            -
            #   in @status. Cookies from @cookies are included at the end of processing.
         
     | 
| 
      
 418 
     | 
    
         
            +
            # Controllers are the classes that do the actual handling and processing of
         
     | 
| 
      
 419 
     | 
    
         
            +
            # requests. The number of normal methods is kept low to prevent clobbering by
         
     | 
| 
      
 420 
     | 
    
         
            +
            # user defined methods.
         
     | 
| 
      
 421 
     | 
    
         
            +
            #
         
     | 
| 
      
 422 
     | 
    
         
            +
            # They may be defined in any location, but if they are defined in a nested
         
     | 
| 
      
 423 
     | 
    
         
            +
            # location within the Maveric class being used to serve at a particular
         
     | 
| 
      
 424 
     | 
    
         
            +
            # location, on instantialization of the Maveric they will automatically
         
     | 
| 
      
 425 
     | 
    
         
            +
            # be added at either the routes specified in their class definition or
         
     | 
| 
      
 426 
     | 
    
         
            +
            # at the default route which is derived from their name and their nesting.
         
     | 
| 
       619 
427 
     | 
    
         
             
            class Maveric::Controller
         
     | 
| 
       620 
     | 
    
         
            -
              REQUEST_METHODS = [:post, :get, :put, :delete, :head] #  
     | 
| 
      
 428 
     | 
    
         
            +
              REQUEST_METHODS = [:post, :get, :put, :delete, :head] # CRUDY
         
     | 
| 
       621 
429 
     | 
    
         | 
| 
       622 
     | 
    
         
            -
              @routes = []
         
     | 
| 
       623 
430 
     | 
    
         
             
              class << self
         
     | 
| 
       624 
     | 
    
         
            -
                ##  
     | 
| 
       625 
     | 
    
         
            -
                 
     | 
| 
       626 
     | 
    
         
            -
             
     | 
| 
      
 431 
     | 
    
         
            +
                ## All children should have routes.
         
     | 
| 
      
 432 
     | 
    
         
            +
                def inherited klass
         
     | 
| 
      
 433 
     | 
    
         
            +
                  klass.class_eval{ @routes = [] }
         
     | 
| 
      
 434 
     | 
    
         
            +
                end
         
     | 
| 
      
 435 
     | 
    
         
            +
                ## Removes currently set routes and adds the stated ones.
         
     | 
| 
      
 436 
     | 
    
         
            +
                def set_routes r, o={}
         
     | 
| 
      
 437 
     | 
    
         
            +
                  ::Maveric.type_check :r, r, String, Array
         
     | 
| 
      
 438 
     | 
    
         
            +
                  clear_routes
         
     | 
| 
      
 439 
     | 
    
         
            +
                  r = [r] unless r.is_a? Array
         
     | 
| 
      
 440 
     | 
    
         
            +
                  r.flatten.map{|e| add_route e }
         
     | 
| 
      
 441 
     | 
    
         
            +
                end
         
     | 
| 
      
 442 
     | 
    
         
            +
                ## Add a route to the Controller.
         
     | 
| 
      
 443 
     | 
    
         
            +
                def add_route r, o={}
         
     | 
| 
      
 444 
     | 
    
         
            +
                  ::Maveric.type_check :r, r, String, ::Maveric::Routing
         
     | 
| 
      
 445 
     | 
    
         
            +
                  r = ::Maveric::Routing.new r, o if r.is_a? String
         
     | 
| 
       627 
446 
     | 
    
         
             
                  @routes << r
         
     | 
| 
       628 
447 
     | 
    
         
             
                end
         
     | 
| 
       629 
     | 
    
         
            -
                 
     | 
| 
      
 448 
     | 
    
         
            +
                ## Removes all currently set routes.
         
     | 
| 
      
 449 
     | 
    
         
            +
                def clear_routes
         
     | 
| 
       630 
450 
     | 
    
         
             
                  @routes.clear
         
     | 
| 
       631 
     | 
    
         
            -
                  r.flatten.map{|e| add_route e }
         
     | 
| 
       632 
451 
     | 
    
         
             
                end
         
     | 
| 
       633 
     | 
    
         
            -
                 
     | 
| 
       634 
     | 
    
         
            -
             
     | 
| 
      
 452 
     | 
    
         
            +
                ## Returns a default Routing based on the #nesting_path if no routes.
         
     | 
| 
      
 453 
     | 
    
         
            +
                def routes
         
     | 
| 
      
 454 
     | 
    
         
            +
                  @routes.empty? ?
         
     | 
| 
      
 455 
     | 
    
         
            +
                    ::Maveric::Routing.new(nesting_path) :
         
     | 
| 
      
 456 
     | 
    
         
            +
                    @routes
         
     | 
| 
       635 
457 
     | 
    
         
             
                end
         
     | 
| 
       636 
     | 
    
         
            -
                attr_reader :routes
         
     | 
| 
       637 
458 
     | 
    
         
             
              end
         
     | 
| 
       638 
459 
     | 
    
         | 
| 
       639 
460 
     | 
    
         
             
              ##
         
     | 
| 
       640 
     | 
    
         
            -
              # Main processing method of Controller. 
     | 
| 
       641 
     | 
    
         
            -
              # 
     | 
| 
       642 
     | 
    
         
            -
              #  
     | 
| 
       643 
     | 
    
         
            -
               
     | 
| 
       644 
     | 
    
         
            -
             
     | 
| 
       645 
     | 
    
         
            -
             
     | 
| 
      
 461 
     | 
    
         
            +
              # Main processing method of Controller.
         
     | 
| 
      
 462 
     | 
    
         
            +
              #
         
     | 
| 
      
 463 
     | 
    
         
            +
              # The response body is set with the result of the specified action method
         
     | 
| 
      
 464 
     | 
    
         
            +
              # if the result is a String and @body has not been set to a String. The
         
     | 
| 
      
 465 
     | 
    
         
            +
              # action method is determined by env[:route][:action], REQUEST_METHOD in
         
     | 
| 
      
 466 
     | 
    
         
            +
              # downcased form, or 'get' by default.
         
     | 
| 
      
 467 
     | 
    
         
            +
              #
         
     | 
| 
      
 468 
     | 
    
         
            +
              # Directly before the action method is called, methods beginning with
         
     | 
| 
      
 469 
     | 
    
         
            +
              # 'prepare_', a number, another '_', and an optional label are called.
         
     | 
| 
      
 470 
     | 
    
         
            +
              # Similarly, after the action method is called, methods beginning with
         
     | 
| 
      
 471 
     | 
    
         
            +
              # 'cleanup_', etc., are called.
         
     | 
| 
      
 472 
     | 
    
         
            +
              #
         
     | 
| 
      
 473 
     | 
    
         
            +
              # By the time the Controller is be instantiated, it should have @status,
         
     | 
| 
      
 474 
     | 
    
         
            +
              # @headers, and @body set. @status should be an Integer matching the
         
     | 
| 
      
 475 
     | 
    
         
            +
              # http status code, @headers a string keyed hash of http headers, and @body
         
     | 
| 
      
 476 
     | 
    
         
            +
              # to a string of the http response body.
         
     | 
| 
      
 477 
     | 
    
         
            +
              def initialize req_body, env, opts={}
         
     | 
| 
      
 478 
     | 
    
         
            +
                ::Maveric.log.warn "Provided env has not been properly processed, results "+
         
     | 
| 
      
 479 
     | 
    
         
            +
                  "may vary!" unless ([:maveric, :route, :params, :cookies]-env.keys).empty?
         
     | 
| 
       646 
480 
     | 
    
         
             
                ::Maveric.type_check :req_body, req_body, IO, StringIO
         
     | 
| 
       647 
     | 
    
         
            -
                Maveric. 
     | 
| 
      
 481 
     | 
    
         
            +
                ::Maveric.type_check :env, env, Hash
         
     | 
| 
      
 482 
     | 
    
         
            +
                ::Maveric.type_check :opts, opts, Hash
         
     | 
| 
      
 483 
     | 
    
         
            +
             
     | 
| 
       648 
484 
     | 
    
         
             
                @status, @headers = 200, {'Content-Type'=>'text/html'}
         
     | 
| 
       649 
     | 
    
         
            -
                @env = env
         
     | 
| 
       650 
     | 
    
         
            -
                @in = req_body
         
     | 
| 
      
 485 
     | 
    
         
            +
                @env, @in = env, req_body
         
     | 
| 
       651 
486 
     | 
    
         
             
                @cookies = @env[:cookies].dup
         
     | 
| 
       652 
     | 
    
         
            -
                method = (@env['REQUEST_METHOD'] || 'get').downcase
         
     | 
| 
       653 
487 
     | 
    
         | 
| 
       654 
     | 
    
         
            -
                 
     | 
| 
       655 
     | 
    
         
            -
             
     | 
| 
      
 488 
     | 
    
         
            +
                action = if @env.key? :route and @env[:route].key? :action
         
     | 
| 
      
 489 
     | 
    
         
            +
                           @env[:route][:action]
         
     | 
| 
      
 490 
     | 
    
         
            +
                         elsif @env.key? 'REQUEST_METHOD'
         
     | 
| 
      
 491 
     | 
    
         
            +
                           @env['REQUEST_METHOD'].downcase
         
     | 
| 
      
 492 
     | 
    
         
            +
                         else 'get' end
         
     | 
| 
      
 493 
     | 
    
         
            +
                raise NoMethodError, [503, "#{action} not implemented.", nil, @env] if \
         
     | 
| 
      
 494 
     | 
    
         
            +
                  REQUEST_METHODS.include? action and not respond_to? action
         
     | 
| 
       656 
495 
     | 
    
         | 
| 
       657 
     | 
    
         
            -
                 
     | 
| 
       658 
     | 
    
         
            -
                 
     | 
| 
       659 
     | 
    
         
            -
             
     | 
| 
       660 
     | 
    
         
            -
             
     | 
| 
       661 
     | 
    
         
            -
             
     | 
| 
       662 
     | 
    
         
            -
                 
     | 
| 
       663 
     | 
    
         
            -
                Maveric.log.debug self
         
     | 
| 
      
 496 
     | 
    
         
            +
                methods.sort.each{|m| __send__ m if /^prepare_\d+_/=~m }
         
     | 
| 
      
 497 
     | 
    
         
            +
                result = __send__(action)
         
     | 
| 
      
 498 
     | 
    
         
            +
                @body = result unless @body.is_a? String or not result.is_a? String
         
     | 
| 
      
 499 
     | 
    
         
            +
                methods.sort.each{|m| __send__ m if /^cleanup_\d+_/=~m }
         
     | 
| 
      
 500 
     | 
    
         
            +
             
     | 
| 
      
 501 
     | 
    
         
            +
                ::Maveric.log.debug self # omg, masochistic.
         
     | 
| 
       664 
502 
     | 
    
         
             
              end
         
     | 
| 
       665 
503 
     | 
    
         | 
| 
       666 
504 
     | 
    
         
             
              attr_reader :status, :headers, :body
         
     | 
| 
       667 
505 
     | 
    
         | 
| 
       668 
     | 
    
         
            -
              ##
         
     | 
| 
       669 
     | 
    
         
            -
              # This is the new renderer. It uses nothing. Yay, configurability!
         
     | 
| 
      
 506 
     | 
    
         
            +
              ## TODO: Doc me.
         
     | 
| 
       670 
507 
     | 
    
         
             
              def render view, s=''
         
     | 
| 
       671 
     | 
    
         
            -
                Maveric.log.debug "#{self.class}#render"+
         
     | 
| 
       672 
     | 
    
         
            -
                  " #{view.inspect}, #{s}"
         
     | 
| 
      
 508 
     | 
    
         
            +
                ::Maveric.log.debug "#{self.class}#render"+
         
     | 
| 
      
 509 
     | 
    
         
            +
                  " #{view.inspect}, #{s.inspect}" # s is painful to logs.
         
     | 
| 
       673 
510 
     | 
    
         
             
                ::Maveric.type_check :view, view, Symbol, String
         
     | 
| 
       674 
     | 
    
         
            -
                 
     | 
| 
       675 
     | 
    
         
            -
                 
     | 
| 
       676 
     | 
    
         
            -
             
     | 
| 
       677 
     | 
    
         
            -
             
     | 
| 
       678 
     | 
    
         
            -
             
     | 
| 
       679 
     | 
    
         
            -
                Maveric.log.info "#{self.class}#render #{view.inspect}\n#{n}".chomp
         
     | 
| 
      
 511 
     | 
    
         
            +
                ::Maveric.type_check :s, s, String
         
     | 
| 
      
 512 
     | 
    
         
            +
                s = yield s if block_given?
         
     | 
| 
      
 513 
     | 
    
         
            +
                s = __send__ view, s if respond_to? view
         
     | 
| 
      
 514 
     | 
    
         
            +
                s = render :layout, s unless view.to_s[/^(_|layout$)/] \
         
     | 
| 
      
 515 
     | 
    
         
            +
                  or caller.any?{|l|l=~/`render'/} # i don't like this 
         
     | 
| 
       680 
516 
     | 
    
         
             
                return s
         
     | 
| 
       681 
517 
     | 
    
         
             
              end
         
     | 
| 
       682 
518 
     | 
    
         | 
| 
       683 
     | 
    
         
            -
              ##  
     | 
| 
       684 
     | 
    
         
            -
              def  
     | 
| 
       685 
     | 
    
         
            -
                 
     | 
| 
       686 
     | 
    
         
            -
             
     | 
| 
       687 
     | 
    
         
            -
             
     | 
| 
       688 
     | 
    
         
            -
                  @body.dup.freeze, 
         
     | 
| 
       689 
     | 
    
         
            -
                  (@env.dup.freeze rescue @env)
         
     | 
| 
       690 
     | 
    
         
            -
                ].freeze
         
     | 
| 
      
 519 
     | 
    
         
            +
              ## For quick and raw response printing!
         
     | 
| 
      
 520 
     | 
    
         
            +
              def to_http
         
     | 
| 
      
 521 
     | 
    
         
            +
                response = "Status: #{@status}" + ::Maveric::EOL
         
     | 
| 
      
 522 
     | 
    
         
            +
                response << @headers.map{|k,v| "#{k}: #{v}" }*::Maveric::EOL
         
     | 
| 
      
 523 
     | 
    
         
            +
                response << ::Maveric::EOL*2 + @body
         
     | 
| 
       691 
524 
     | 
    
         
             
              end
         
     | 
| 
       692 
525 
     | 
    
         | 
| 
       693 
     | 
    
         
            -
              ## 
     | 
| 
       694 
     | 
    
         
            -
               
     | 
| 
       695 
     | 
    
         
            -
             
     | 
| 
       696 
     | 
    
         
            -
             
     | 
| 
       697 
     | 
    
         
            -
                 
     | 
| 
      
 526 
     | 
    
         
            +
              ##
         
     | 
| 
      
 527 
     | 
    
         
            +
              # Extends the Controller instance with the Views and Models modules of the
         
     | 
| 
      
 528 
     | 
    
         
            +
              # pertinant Maveric instance.
         
     | 
| 
      
 529 
     | 
    
         
            +
              def prepare_0_imports
         
     | 
| 
      
 530 
     | 
    
         
            +
                extend @env[:maveric].class::Models
         
     | 
| 
      
 531 
     | 
    
         
            +
                extend @env[:maveric].class::Views
         
     | 
| 
       698 
532 
     | 
    
         
             
              end
         
     | 
| 
       699 
     | 
    
         
            -
             
     | 
| 
       700 
533 
     | 
    
         
             
              ##
         
     | 
| 
       701 
     | 
    
         
            -
              #  
     | 
| 
       702 
     | 
    
         
            -
              #  
     | 
| 
       703 
     | 
    
         
            -
               
     | 
| 
       704 
     | 
    
         
            -
             
     | 
| 
       705 
     | 
    
         
            -
             
     | 
| 
       706 
     | 
    
         
            -
                   
     | 
| 
       707 
     | 
    
         
            -
                 
     | 
| 
       708 
     | 
    
         
            -
                  REQUEST_METHODS.include? m
         
     | 
| 
       709 
     | 
    
         
            -
                super m, *a, &b
         
     | 
| 
      
 534 
     | 
    
         
            +
              # Folds the datasets of @cookie to @headers if they have been altered or
         
     | 
| 
      
 535 
     | 
    
         
            +
              # are new.
         
     | 
| 
      
 536 
     | 
    
         
            +
              def cleanup_0_cookies
         
     | 
| 
      
 537 
     | 
    
         
            +
                @cookies.each do |k,v|
         
     | 
| 
      
 538 
     | 
    
         
            +
                  next unless v != @env[:cookies][k]
         
     | 
| 
      
 539 
     | 
    
         
            +
                  @headers['Set-Cookie'] << "#{k}=#{::Maveric.escape(v)}"
         
     | 
| 
      
 540 
     | 
    
         
            +
                end
         
     | 
| 
       710 
541 
     | 
    
         
             
              end
         
     | 
| 
       711 
542 
     | 
    
         
             
            end
         
     | 
| 
       712 
543 
     | 
    
         | 
| 
       713 
544 
     | 
    
         
             
            ##
         
     | 
| 
       714 
     | 
    
         
            -
            #  
     | 
| 
       715 
     | 
    
         
            -
            #  
     | 
| 
       716 
     | 
    
         
            -
             
     | 
| 
       717 
     | 
    
         
            -
             
     | 
| 
       718 
     | 
    
         
            -
            # 
     | 
| 
       719 
     | 
    
         
            -
             
     | 
| 
       720 
     | 
    
         
            -
            #  
     | 
| 
       721 
     | 
    
         
            -
             
     | 
| 
       722 
     | 
    
         
            -
               
     | 
| 
       723 
     | 
    
         
            -
             
     | 
| 
       724 
     | 
    
         
            -
             
     | 
| 
       725 
     | 
    
         
            -
             
     | 
| 
       726 
     | 
    
         
            -
             
     | 
| 
       727 
     | 
    
         
            -
             
     | 
| 
      
 545 
     | 
    
         
            +
            # Instances of Route are used for determining how to act upon particular urls
         
     | 
| 
      
 546 
     | 
    
         
            +
            # in each Maveric instance. They are magical and simply complex creatures.
         
     | 
| 
      
 547 
     | 
    
         
            +
            class Maveric::Routing < Regexp
         
     | 
| 
      
 548 
     | 
    
         
            +
              URI_CHAR = '[^/?:,&#]'
         
     | 
| 
      
 549 
     | 
    
         
            +
              PARAM_MATCH= %r~:(#{URI_CHAR}+):?~
         
     | 
| 
      
 550 
     | 
    
         
            +
              ##
         
     | 
| 
      
 551 
     | 
    
         
            +
              # The String path is turned into a regex in a very straightforward manner. 
         
     | 
| 
      
 552 
     | 
    
         
            +
              # Fragments of the path that begin with ':' followed by any number of
         
     | 
| 
      
 553 
     | 
    
         
            +
              # characters that aren't a typical URI delimiter or reserved character, and
         
     | 
| 
      
 554 
     | 
    
         
            +
              # optionally ending with another ':', are indicators of paramæters.
         
     | 
| 
      
 555 
     | 
    
         
            +
              #
         
     | 
| 
      
 556 
     | 
    
         
            +
              # Parameters are typically replaced with the regexp of /(#{URI_CHAR}+)/ in
         
     | 
| 
      
 557 
     | 
    
         
            +
              # the Routing instance. If the parameter label matches a key in opts, the 
         
     | 
| 
      
 558 
     | 
    
         
            +
              # associated value is placed into the Routing instead.
         
     | 
| 
      
 559 
     | 
    
         
            +
              def initialize path, opts={}
         
     | 
| 
      
 560 
     | 
    
         
            +
                ::Maveric.type_check :path, path, String
         
     | 
| 
      
 561 
     | 
    
         
            +
                ::Maveric.type_check :opts, opts, Hash
         
     | 
| 
      
 562 
     | 
    
         
            +
             
     | 
| 
      
 563 
     | 
    
         
            +
                @path = path.dup.freeze
         
     | 
| 
      
 564 
     | 
    
         
            +
                @options = opts.dup.freeze
         
     | 
| 
      
 565 
     | 
    
         
            +
             
     | 
| 
      
 566 
     | 
    
         
            +
                @params = []
         
     | 
| 
      
 567 
     | 
    
         
            +
                regex = path.gsub PARAM_MATCH do
         
     | 
| 
      
 568 
     | 
    
         
            +
                  param = $1.to_sym
         
     | 
| 
      
 569 
     | 
    
         
            +
                  raise ArgumentError, "Duplicated parameters in path."+
         
     | 
| 
      
 570 
     | 
    
         
            +
                    " <#{param.inspect}>" if @params.include? param
         
     | 
| 
      
 571 
     | 
    
         
            +
                  @params << param
         
     | 
| 
      
 572 
     | 
    
         
            +
                  "(#{opts[param] || URI_CHAR+'+'})"
         
     | 
| 
       728 
573 
     | 
    
         
             
                end
         
     | 
| 
       729 
     | 
    
         
            -
                 
     | 
| 
       730 
     | 
    
         
            -
                 
     | 
| 
      
 574 
     | 
    
         
            +
                @params.freeze
         
     | 
| 
      
 575 
     | 
    
         
            +
                super %r~^#{regex}$~iu.freeze
         
     | 
| 
      
 576 
     | 
    
         
            +
             
     | 
| 
      
 577 
     | 
    
         
            +
                ::Maveric.log.debug self.inspect
         
     | 
| 
       731 
578 
     | 
    
         
             
              end
         
     | 
| 
       732 
     | 
    
         
            -
            end
         
     | 
| 
       733 
579 
     | 
    
         | 
| 
       734 
     | 
    
         
            -
             
     | 
| 
       735 
     | 
    
         
            -
            module Maveric::Models
         
     | 
| 
       736 
     | 
    
         
            -
            end
         
     | 
| 
      
 580 
     | 
    
         
            +
              attr_reader :path, :params
         
     | 
| 
       737 
581 
     | 
    
         | 
| 
       738 
     | 
    
         
            -
            ##
         
     | 
| 
       739 
     | 
    
         
            -
            #  
     | 
| 
       740 
     | 
    
         
            -
            #  
     | 
| 
       741 
     | 
    
         
            -
            #
         
     | 
| 
       742 
     | 
    
         
            -
            #  
     | 
| 
       743 
     | 
    
         
            -
            #  
     | 
| 
       744 
     | 
    
         
            -
             
     | 
| 
       745 
     | 
    
         
            -
            # 
     | 
| 
       746 
     | 
    
         
            -
             
     | 
| 
       747 
     | 
    
         
            -
             
     | 
| 
       748 
     | 
    
         
            -
             
     | 
| 
       749 
     | 
    
         
            -
             
     | 
| 
       750 
     | 
    
         
            -
                proc{|h| Maveric.query_parse(h['HTTP_COOKIE'], ';,') },
         
     | 
| 
       751 
     | 
    
         
            -
                :params,
         
     | 
| 
       752 
     | 
    
         
            -
                proc{|h| Maveric.query_parse(h['QUERY_STRING']) }
         
     | 
| 
       753 
     | 
    
         
            -
              ]
         
     | 
| 
       754 
     | 
    
         
            -
             
     | 
| 
       755 
     | 
    
         
            -
              ## If a key has no assigned value then test to see if there's a generator.
         
     | 
| 
       756 
     | 
    
         
            -
              def default k
         
     | 
| 
       757 
     | 
    
         
            -
                unless @@gen_on_key.key? k then super k
         
     | 
| 
       758 
     | 
    
         
            -
                else store k, @@gen_on_key[k][self]
         
     | 
| 
      
 582 
     | 
    
         
            +
              ##
         
     | 
| 
      
 583 
     | 
    
         
            +
              # If given a hash that contains all of and only contains keys matching its
         
     | 
| 
      
 584 
     | 
    
         
            +
              # parameters then a path will be built by interpolating the hash values for
         
     | 
| 
      
 585 
     | 
    
         
            +
              # their corresponding parameters.
         
     | 
| 
      
 586 
     | 
    
         
            +
              # NOTE: Should I or should I not test the result against itself to ensure
         
     | 
| 
      
 587 
     | 
    
         
            +
              # the generation of a matching path?
         
     | 
| 
      
 588 
     | 
    
         
            +
              def build arg
         
     | 
| 
      
 589 
     | 
    
         
            +
                ::Maveric.log.debug "#{self.class}#build"+
         
     | 
| 
      
 590 
     | 
    
         
            +
                  " #{arg.inspect} : #{self.inspect}"
         
     | 
| 
      
 591 
     | 
    
         
            +
                ::Maveric.type_check :arg, arg, Hash
         
     | 
| 
      
 592 
     | 
    
         
            +
                if @params.sort == arg.keys.sort
         
     | 
| 
      
 593 
     | 
    
         
            +
                  path = arg.inject(@path){|r,(k,v)| r.sub /:#{k}:?/, v }
         
     | 
| 
       759 
594 
     | 
    
         
             
                end
         
     | 
| 
       760 
595 
     | 
    
         
             
              end
         
     | 
| 
       761 
596 
     | 
    
         | 
| 
       762 
     | 
    
         
            -
              ## 
     | 
| 
       763 
     | 
    
         
            -
               
     | 
| 
       764 
     | 
    
         
            -
             
     | 
| 
       765 
     | 
    
         
            -
             
     | 
| 
       766 
     | 
    
         
            -
             
     | 
| 
      
 597 
     | 
    
         
            +
              ##
         
     | 
| 
      
 598 
     | 
    
         
            +
              # When given a path that matches the Routing itself, a hash is returned with
         
     | 
| 
      
 599 
     | 
    
         
            +
              # keys being parameters and values being the associated value gathered from
         
     | 
| 
      
 600 
     | 
    
         
            +
              # the path.
         
     | 
| 
      
 601 
     | 
    
         
            +
              def route path
         
     | 
| 
      
 602 
     | 
    
         
            +
                ::Maveric.log.debug "#{self.class}#route"+
         
     | 
| 
      
 603 
     | 
    
         
            +
                  " #{path.inspect} : #{self.inspect}"
         
     | 
| 
      
 604 
     | 
    
         
            +
                ::Maveric.type_check :path, path, String
         
     | 
| 
      
 605 
     | 
    
         
            +
                if self =~ path
         
     | 
| 
      
 606 
     | 
    
         
            +
                  Hash[ *@params.zip($~.captures).flatten ].update(nil => self)
         
     | 
| 
       767 
607 
     | 
    
         
             
                end
         
     | 
| 
       768 
608 
     | 
    
         
             
              end
         
     | 
| 
      
 609 
     | 
    
         
            +
             
     | 
| 
      
 610 
     | 
    
         
            +
              ##
         
     | 
| 
      
 611 
     | 
    
         
            +
              # This is an attempt as path correction. Root is treated as a prefix to the
         
     | 
| 
      
 612 
     | 
    
         
            +
              # generating path to be removed, from which a new Routing will be spawned.
         
     | 
| 
      
 613 
     | 
    
         
            +
              def adjust root, opts={}
         
     | 
| 
      
 614 
     | 
    
         
            +
                ::Maveric.type_check :root, root, String
         
     | 
| 
      
 615 
     | 
    
         
            +
                self.class.new @path.sub(/^#{root}/,'/'), @options.merge(opts)
         
     | 
| 
      
 616 
     | 
    
         
            +
              end
         
     | 
| 
      
 617 
     | 
    
         
            +
             
     | 
| 
      
 618 
     | 
    
         
            +
              ##
         
     | 
| 
      
 619 
     | 
    
         
            +
              # As Routing is a subclass of a corelib class, the inspect isn't as
         
     | 
| 
      
 620 
     | 
    
         
            +
              # informative as we'd like. So we override it.
         
     | 
| 
      
 621 
     | 
    
         
            +
              def inspect
         
     | 
| 
      
 622 
     | 
    
         
            +
                v = [object_id<<1].pack('i').unpack('I')[0] # faster
         
     | 
| 
      
 623 
     | 
    
         
            +
                "#<#{self.class}:0x#{v.to_s(16)} #{super}"+
         
     | 
| 
      
 624 
     | 
    
         
            +
                  " #{@path.inspect} #{@params.inspect}>"
         
     | 
| 
      
 625 
     | 
    
         
            +
              end
         
     | 
| 
       769 
626 
     | 
    
         
             
            end
         
     |