# Module: Capcode
[ "README", "AUTHORS", "COPYING", "lib/capcode.rb", nil].each do
Capcode.view_html
Capcode::Views.view_html
Capcode::Helpers.view_html
Capcode::HTTPError.view_html
Capcode::RenderError.view_html
Capcode::RouteError.view_html
Capcode::ParameterError.view_html
end

Module Capcode

(in files lib/capcode.rb )

Includes

Methods

Public Class method: Route(*u)

Add routes to a controller class

  module Capcode
    class Hello < Route '/hello/(.*)', '/hello/([^#]*)#(.*)'
      def get( arg1, arg2 )
        ...
      end
    end
  end

In the get method, you will receive the maximum of parameters declared by the routes. In this example, you will receive 2 parameters. So if you go to /hello/world#friend then arg1 will be set to world and arg2 will be set to friend. Now if you go to /hello/you, then arg1 will be set to you and arg2 will be set to nil

If the regexp in the route does not match, all arguments will be nil

     # File lib/capcode.rb, line 248
248:     def Route *u
249:       Class.new {
250:         meta_def(:__urls__){
251:           # < Route '/hello/world/([^\/]*)/id(\d*)', '/hello/(.*)'
252:           # # => [ {'/hello/world' => '([^\/]*)/id(\d*)', '/hello' => '(.*)'}, 2, <Capcode::Klass> ]
253:           h = {}
254:           max = 0
255:           u.each do |_u|
256:             m = /\/([^\/]*\(.*)/.match( _u )
257:             if m.nil?
258:               raise Capcode::RouteError, "Route `#{_u}' already defined with regexp `#{h[_u]}' !", caller if h.keys.include?(_u)
259:               h[_u] = ''
260:             else
261:               _pre = m.pre_match
262:               _pre = "/" if _pre.size == 0
263:               raise Capcode::RouteError, "Route `#{_pre}' already defined with regexp `#{h[_pre]}' !", caller if h.keys.include?(_pre)
264:               h[_pre] = m.captures[0]
265:               max = Regexp.new(m.captures[0]).number_of_captures if max < Regexp.new(m.captures[0]).number_of_captures
266:             end
267:           end
268:           [h, max, self]
269:         }
270: 
271:         # Hash containing all the request parameters (GET or POST)
272:         def params
273:           @request.params
274:         end
275:         
276:         # Hash containing all the environment variables
277:         def env
278:           @env
279:         end
280:         
281:         # Hash session
282:         def session
283:           @env['rack.session']
284:         end
285:         
286:         # Return the Rack::Request object
287:         def request
288:           @request
289:         end
290:         
291:         # Return the Rack::Response object
292:         def response
293:           @response
294:         end
295:         
296:         def call( e ) #:nodoc:
297:           @env = e
298:           @response = Rack::Response.new
299:           @request = Rack::Request.new(@env)
300: 
301:           # __k = self.class.to_s.split( /::/ )[-1].downcase.to_sym
302:           # @@__FILTERS.each do |f|
303:           #   proc = f.delete(:action)
304:           #   __run = true
305:           #   if f[:only]
306:           #     __run = f[:only].include?(__k)
307:           #   end
308:           #   if f[:except]
309:           #     __run = !f[:except].include?(__k)
310:           #   end
311:           #   
312:           #   # proc.call(self) if __run
313:           #   puts "call #{proc} for #{__k}"
314:           # end
315: 
316:           r = case @env["REQUEST_METHOD"]
317:             when "GET"
318:               finalPath = nil
319:               finalArgs = nil
320:               finalNArgs = nil
321:               
322:               aPath = @request.path.gsub( /^\//, "" ).split( "/" )
323:               self.class.__urls__[0].each do |p, r|
324:                 xPath = p.gsub( /^\//, "" ).split( "/" )
325:                 if (xPath - aPath).size == 0
326:                   diffArgs = aPath - xPath
327:                   diffNArgs = diffArgs.size
328:                   if finalNArgs.nil? or finalNArgs > diffNArgs
329:                     finalPath = p
330:                     finalNArgs = diffNArgs
331:                     finalArgs = diffArgs
332:                   end
333:                 end
334:                 
335:               end
336: 
337:               nargs = self.class.__urls__[1]
338:               regexp = Regexp.new( self.class.__urls__[0][finalPath] )
339:               args = regexp.match( Rack::Utils.unescape(@request.path).gsub( Regexp.new( "^#{finalPath}" ), "" ).gsub( /^\//, "" ) )
340:               if args.nil?
341:                 raise Capcode::ParameterError, "Path info `#{@request.path_info}' does not match route regexp `#{regexp.source}'"
342:               else
343:                 args = args.captures.map { |x| (x.size == 0)?nil:x }
344:               end
345:               
346:               while args.size < nargs
347:                 args << nil
348:               end
349:                     
350:               get( *args )
351:             when "POST"
352:               post
353:           end
354:           if r.respond_to?(:to_ary)
355:             @response.status = r[0]
356:             r[1].each do |k,v|
357:               @response[k] = v
358:             end
359:             @response.body = r[2]
360:           else
361:             @response.write r
362:           end
363:           
364:           @response.finish
365:         end
366:                 
367:         include Capcode::Helpers
368:         include Capcode::Views
369:       }      
370:     end

Public Class method: env()

Hash containing all the environment variables

     # File lib/capcode.rb, line 277
277:         def env
278:           @env
279:         end

Public Class method: map( r ) {|| ...}

This method help you to map and URL to a Rack or What you want Helper

  Capcode.map( "/file" ) do
    Rack::File.new( "." )
  end
     # File lib/capcode.rb, line 377
377:     def map( r, &b )
378:       @@__ROUTES[r] = yield
379:     end

Public Class method: params()

Hash containing all the request parameters (GET or POST)

     # File lib/capcode.rb, line 272
272:         def params
273:           @request.params
274:         end

Public Class method: request()

Return the Rack::Request object

     # File lib/capcode.rb, line 287
287:         def request
288:           @request
289:         end

Public Class method: response()

Return the Rack::Response object

     # File lib/capcode.rb, line 292
292:         def response
293:           @response
294:         end

Public Class method: run( args = {} ) {|self| ...}

Start your application.

Options :

  • :port = Listen port
  • :host = Listen host
  • :server = Server type (webrick or mongrel)
  • :log = Output logfile (default: STDOUT)
  • :session = Session parameters. See Rack::Session for more informations
  • :pid = PID file (default: $0.pid)
  • :daemonize = Daemonize application (default: false)
  • :db_config = database configuration file (default: database.yml)
  • :root = root directory (default: "." — relative to the working directory)
  • :working_directory = Working directory (default: directory of the main.rb)
     # File lib/capcode.rb, line 394
394:     def run( args = {} )
395:       conf = {
396:         :port => args[:port]||3000, 
397:         :host => args[:host]||"localhost",
398:         :server => args[:server]||nil,
399:         :log => args[:log]||$stdout,
400:         :session => args[:session]||{},
401:         :pid => args[:pid]||"#{$0}.pid",
402:         :daemonize => args[:daemonize]||false,
403:         :db_config => args[:db_config]||"database.yml",
404:         :root => args[:root]||".",
405:         :working_directory => args[:working_directory]||File.expand_path(File.dirname($0)),
406:         
407:         :console => false
408:       }
409:       
410:       # Parse options
411:       opts = OptionParser.new do |opts|
412:         opts.banner = "Usage: #{File.basename($0)} [options]"
413:         opts.separator ""
414:         opts.separator "Specific options:"
415: 
416:         opts.on( "-C", "--console", "Run in console mode with IRB (default: false)" ) { 
417:           conf[:console] = true
418:         }
419:         opts.on( "-h", "--host HOSTNAME", "Host for web server to bind to (default: #{conf[:host]})" ) { |h|
420:           conf[:host] = h
421:         }
422:         opts.on( "-p", "--port NUM", "Port for web server (default: #{conf[:port]})" ) { |p|
423:           conf[:port] = p
424:         }
425:         opts.on( "-d", "--daemonize [true|false]", "Daemonize (default: #{conf[:daemonize]})" ) { |d|
426:           conf[:daemonize] = d
427:         }
428: 
429:         opts.separator ""
430:         opts.separator "Common options:"
431: 
432:         opts.on_tail("-?", "--help", "Show this message") do
433:           puts opts
434:           exit
435:         end  
436:       end
437:       
438:       begin
439:         opts.parse! ARGV
440:       rescue OptionParser::ParseError => ex
441:         STDERR.puts "!! #{ex.message}"
442:         puts "** use `#{File.basename($0)} --help` for more details..."
443:         exit 1
444:       end
445:       
446:       # Run in the Working directory
447:       Dir.chdir( conf[:working_directory] ) do
448:         # Set root directory for helpers
449:         Capcode::Helpers.root = File.expand_path( conf[:root] )
450:         
451:         # Check that mongrel exists 
452:         if conf[:server].nil? || conf[:server] == "mongrel"
453:           begin
454:             require 'mongrel'
455:             conf[:server] = "mongrel"
456:           rescue LoadError 
457:             puts "!! could not load mongrel. Falling back to webrick."
458:             conf[:server] = "webrick"
459:           end
460:         end
461:             
462:         Capcode.constants.each do |k|
463:           begin
464:             if eval "Capcode::#{k}.public_methods(true).include?( '__urls__' )"
465:               u, m, c = eval "Capcode::#{k}.__urls__"
466:               u.keys.each do |_u|
467:                 raise Capcode::RouteError, "Route `#{_u}' already define !", caller if @@__ROUTES.keys.include?(_u)
468:                 @@__ROUTES[_u] = c.new
469:               end
470:             end
471:           rescue => e
472:             raise e.message
473:           end
474:         end
475:         
476:         app = Rack::URLMap.new(@@__ROUTES)
477:         app = Rack::Session::Cookie.new( app, conf[:session] )
478:         app = Capcode::HTTPError.new(app, conf[:root])
479:         app = Rack::ContentLength.new(app)
480:         app = Rack::Lint.new(app)
481:         app = Rack::ShowExceptions.new(app)
482: #        app = Rack::Reloader.new(app) ## -- NE RELOAD QUE capcode.rb -- So !!!
483:         app = Rack::CommonLogger.new( app, Logger.new(conf[:log]) )
484:         
485:         # From rackup !!!
486:         if conf[:daemonize]
487:           if RUBY_VERSION < "1.9"
488:             exit if fork
489:             Process.setsid
490:             exit if fork
491:             # Dir.chdir "/"
492:             File.umask 0000
493:             STDIN.reopen "/dev/null"
494:             STDOUT.reopen "/dev/null", "a"
495:             STDERR.reopen "/dev/null", "a"
496:           else
497:             Process.daemon
498:           end
499:         
500:           File.open(conf[:pid], 'w'){ |f| f.write("#{Process.pid}") }
501:           at_exit { File.delete(conf[:pid]) if File.exist?(conf[:pid]) }
502:         end
503:         
504:         # Start database
505:         if self.methods.include? "db_connect"
506:           db_connect( conf[:db_config], conf[:log] )
507:         end
508:         
509:         if block_given?
510:           yield( self )
511:         end
512:         
513:         if conf[:console]
514:           puts "Run console..."
515:           IRB.start
516:           exit
517:         end
518:         
519:         # Start server
520:         case conf[:server]
521:         when "mongrel"
522:           puts "** Starting Mongrel on #{conf[:host]}:#{conf[:port]}"
523:           Rack::Handler::Mongrel.run( app, {:Port => conf[:port], :Host => conf[:host]} ) { |server|
524:             trap "SIGINT", proc { server.stop }
525:           }
526:         when "webrick"
527:           puts "** Starting WEBrick on #{conf[:host]}:#{conf[:port]}"
528:           Rack::Handler::WEBrick.run( app, {:Port => conf[:port], :BindAddress => conf[:host]} ) { |server|
529:             trap "SIGINT", proc { server.shutdown }
530:           }
531:         end
532:       end
533:     end

Public Class method: session()

Hash session

     # File lib/capcode.rb, line 282
282:         def session
283:           @env['rack.session']
284:         end