Module Capcode
In: lib/capcode.rb
lib/capcode/base/db.rb
lib/capcode/configuration.rb
lib/capcode/filters.rb
lib/capcode/render/text.rb
lib/capcode/helpers/auth.rb

Methods

Route   application   before_filter   env   http_authentication   logger   map   params   request   response   run   session   set   use  

Included Modules

Rack Capcode::Helpers Capcode::Views

Classes and Modules

Module Capcode::Helpers
Module Capcode::Resource
Module Capcode::Views
Class Capcode::Base
Class Capcode::Configuration
Class Capcode::HTTPError

Constants

Route = Capcode::Route(nil)

Attributes

__auth__  [RW] 

Public Class methods

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

[Source]

     # File lib/capcode.rb, line 368
368:     def Route *routes_paths
369:       create_path = routes_paths[0].nil?
370:       Class.new {
371:         meta_def(:__urls__) {
372:           routes_paths = ['/'+self.to_s.gsub( /^Capcode::/, "" ).underscore] if create_path == true
373:           # < Route '/hello/world/([^\/]*)/id(\d*)', '/hello/(.*)', :agent => /Songbird (\d\.\d)[\d\/]*?/
374:           # # => [ {'/hello/world' => '([^\/]*)/id(\d*)', '/hello' => '(.*)'}, 
375:           #        2, 
376:           #        <Capcode::Klass>, 
377:           #        {:agent => /Songbird (\d\.\d)[\d\/]*?/} ]
378:           hash_of_routes = {}
379:           max_captures_for_routes = 0
380:           routes_paths.each do |current_route_path|
381:             if current_route_path.class == String
382:               m = /\/([^\/]*\(.*)/.match( current_route_path )
383:               if m.nil?
384:                 raise Capcode::RouteError, "Route `#{current_route_path}' already defined with regexp `#{hash_of_routes[current_route_path]}' !", caller if hash_of_routes.keys.include?(current_route_path)
385:                 hash_of_routes[current_route_path] = ''
386:               else
387:                 _pre = m.pre_match
388:                 _pre = "/" if _pre.size == 0
389:                 raise Capcode::RouteError, "Route `#{_pre}' already defined with regexp `#{hash_of_routes[_pre]}' !", caller if hash_of_routes.keys.include?(_pre)
390:                 hash_of_routes[_pre] = m.captures[0]
391:                 max_captures_for_routes = Regexp.new(m.captures[0]).number_of_captures if max_captures_for_routes < Regexp.new(m.captures[0]).number_of_captures
392:               end
393:             else
394:               raise Capcode::ParameterError, "Bad route declaration !", caller
395:             end
396:           end
397:           [hash_of_routes, max_captures_for_routes, self]
398:         }
399:                 
400:         # Hash containing all the request parameters (GET or POST)
401:         def params
402:           @request.params
403:         end
404:         
405:         # Hash containing all the environment variables
406:         def env
407:           @env
408:         end
409:         
410:         # Session hash
411:         def session
412:           @env['rack.session']
413:         end
414:         
415:         # Return the Rack::Request object
416:         def request
417:           @request
418:         end
419:         
420:         # Return the Rack::Response object
421:         def response
422:           @response
423:         end
424:         
425:         def call( e ) #:nodoc:
426:           @env = e
427:           @response = Rack::Response.new
428:           @request = Rack::Request.new(@env)
429: 
430:           # Check authz
431:           authz_options = nil
432:           if Capcode.__auth__ and Capcode.__auth__.size > 0
433:             authz_options = Capcode.__auth__[@request.path]||nil
434:             if authz_options.nil?
435:               route = nil
436:               
437:               Capcode.__auth__.each do |r, o|
438:                 regexp = "^#{r.gsub(/\/$/, "")}([/]{1}.*)?$"
439:                 if Regexp.new(regexp).match( @request.path )
440:                   if route.nil? or r.size > route.size
441:                     route = r
442:                     authz_options = o
443:                   end
444:                 end  
445:               end
446:             end
447:           end
448: 
449:           r = catch(:halt) { 
450:             unless authz_options.nil?
451:               http_authentication( :type => authz_options[:type], :realm => authz_options[:realm], :opaque => authz_options[:realm] ) { 
452:                 authz_options[:autz]
453:               }
454:             end
455: 
456:             finalPath = nil
457:             finalArgs = nil
458:             finalNArgs = nil
459:             
460:             aPath = @request.path.gsub( /^\//, "" ).split( "/" )
461:             self.class.__urls__[0].each do |p, r|
462:               xPath = p.gsub( /^\//, "" ).split( "/" )
463:               if (xPath - aPath).size == 0
464:                 diffArgs = aPath - xPath
465:                 diffNArgs = diffArgs.size - 1
466:                 if finalNArgs.nil? or finalNArgs > diffNArgs
467:                   finalPath = p
468:                   finalNArgs = diffNArgs
469:                   finalArgs = diffArgs
470:                 end
471:               end
472:             end
473:             
474:             if finalNArgs > self.class.__urls__[1]
475:               return [404, {'Content-Type' => 'text/plain'}, "Not Found: #{@request.path}"]
476:             end
477:         
478:             nargs = self.class.__urls__[1]
479:             regexp = Regexp.new( self.class.__urls__[0][finalPath] )
480:             args = regexp.match( Rack::Utils.unescape(@request.path).gsub( Regexp.new( "^#{finalPath}" ), "" ).gsub( /^\//, "" ) )
481:             if args.nil?
482:               raise Capcode::ParameterError, "Path info `#{@request.path_info}' does not match route regexp `#{regexp.source}'"
483:             else
484:               args = args.captures.map { |x| (x.size == 0)?nil:x }
485:             end
486:             
487:             while args.size < nargs
488:               args << nil
489:             end
490: 
491:             filter_output = Capcode::Filter.execute( self )
492: 
493:             if( filter_output.nil? )
494:               # case @env["REQUEST_METHOD"]
495:               #   when "GET"                      
496:               #     get( *args )
497:               #   when "POST"
498:               #     _method = params.delete( "_method" ) { |_| "post" }
499:               #     send( _method.downcase.to_sym, *args )
500:               #   else
501:               #     _method = @env["REQUEST_METHOD"]
502:               #     send( _method.downcase.to_sym, *args )
503:               # end
504:               begin
505:                 _method = params.delete( "_method" ) { |_| @env["REQUEST_METHOD"] }
506:                 if self.class.method_defined?( _method.downcase.to_sym )
507:                   send( _method.downcase.to_sym, *args )
508:                 else
509:                   any( *args )
510:                 end
511:               rescue => e
512:                 raise e.class, e.to_s
513:               end
514:             else
515:               filter_output
516:             end
517:           }
518:           
519:           if r.respond_to?(:to_ary)
520:             @response.status = r.shift #r[0]
521:             #r[1].each do |k,v|
522:             r.shift.each do |k,v|
523:               @response[k] = v
524:             end
525:             @response.write r.shift #r[2]
526:           else
527:             @response.write r
528:           end
529:           
530:           @response.finish
531:         end
532:                 
533:         include Capcode::Helpers
534:         include Capcode::Views        
535:       }      
536:     end

Return the Rack App.

Options : see Capcode::Configuration.set

Options set here replace the ones set globally

[Source]

     # File lib/capcode.rb, line 605
605:     def application( args = {} )
606:       Capcode::Configuration.configuration(args)
607:       Capcode::Configuration.print_debug if Capcode::Configuration.get(:verbose)
608:       
609:       Capcode.constants.clone.delete_if {|k| 
610:         not( Capcode.const_get(k).to_s =~ /Capcode/ ) or [
611:           "Filter", 
612:           "Helpers", 
613:           "RouteError", 
614:           "Views", 
615:           "ParameterError", 
616:           "HTTPError", 
617:           "Configuration", 
618:           "MissingLibrary", 
619:           "Route", 
620:           "RenderError"
621:         ].include?(k)
622:       }.each do |k|
623:         begin
624:           if eval "Capcode::#{k}.public_methods(true).include?( '__urls__' )"
625:             hash_of_routes, max_captures_for_routes, klass = eval "Capcode::#{k}.__urls__"            
626:             hash_of_routes.keys.each do |current_route_path|
627:               #raise Capcode::RouteError, "Route `#{current_route_path}' already define !", caller if @@__ROUTES.keys.include?(current_route_path)
628:               raise Capcode::RouteError, "Route `#{current_route_path}' already define !", caller if Capcode.routes.keys.include?(current_route_path)
629: #              Capcode.routes[current_route_path] = klass.new
630:               Capcode.routes[current_route_path] = klass
631:             end
632:           end
633:         rescue => e
634:           raise e.message
635:         end
636:       end
637:       
638:       # Set Static directory
639:       Capcode.static = (Capcode::Configuration.get(:static)[0].chr == "/")?Capcode::Configuration.get(:static):"/"+Capcode::Configuration.get(:static) unless Capcode::Configuration.get(:static).nil?
640:       
641:       # Initialize Rack App
642:       puts "** Map routes." if Capcode::Configuration.get(:verbose)
643: #      app = Rack::URLMap.new(Capcode.routes)
644:       app = Capcode::Ext::Rack::URLMap.new(Capcode.routes)
645:       puts "** Initialize static directory (#{Capcode.static}) in #{File.expand_path(Capcode::Configuration.get(:root))}" if Capcode::Configuration.get(:verbose)
646:       app = Rack::Static.new( 
647:         app, 
648:         #:urls => [@@__STATIC_DIR], 
649:         :urls => [Capcode.static], 
650:         :root => File.expand_path(Capcode::Configuration.get(:root)) 
651:       ) unless Capcode::Configuration.get(:static).nil?
652:       puts "** Initialize session" if Capcode::Configuration.get(:verbose)
653:       app = Rack::Session::Cookie.new( app, Capcode::Configuration.get(:session) )
654:       app = Capcode::HTTPError.new(app)
655:       app = Rack::ContentLength.new(app)
656:       app = Rack::Lint.new(app)
657:       app = Rack::ShowExceptions.new(app)
658:       #app = Rack::Reloader.new(app) ## -- NE RELOAD QUE capcode.rb -- So !!!
659:       app = Rack::CommonLogger.new( app, @cclogger = Logger.new(Capcode::Configuration.get(:log)) )
660:       
661:       middlewares.each do |mw|
662:         middleware, args, block = mw
663:         puts "** Load middleware #{middleware}" if Capcode::Configuration.get(:verbose)
664:         if block
665:           app = middleware.new( app, *args, &block )
666:         else
667:           app = middleware.new( app, *args )
668:         end
669:       end
670:       
671:       # Start database
672:       if self.methods.include? "db_connect"
673:         db_connect( Capcode::Configuration.get(:db_config), Capcode::Configuration.get(:log) )
674:       end
675:       
676:       if block_given?
677:         puts "** Execute block" if Capcode::Configuration.get(:verbose)
678:         yield( self )
679:       end
680:       
681:       return app
682:     end

Add a before filter :

  module Capcode
    before_filter :my_global_action
    before_filter :need_login, :except => [:Login]
    before_filter :check_mail, :only => [:MailBox]
    # ...
  end

If the action return nil, the normal get or post will be executed, else no.

[Source]

    # File lib/capcode/filters.rb, line 14
14:     def before_filter( action, opts = {} )
15:       Capcode::Filter.filters[action] = { }
16:       Capcode::Filter.ordered_actions << action
17:       
18:       opts.each do |k, v|
19:         Capcode::Filter.filters[action][k] = v
20:       end
21:     end

Hash containing all the environment variables

[Source]

     # File lib/capcode.rb, line 406
406:         def env
407:           @env
408:         end

Allow you to add and HTTP Authentication (Basic or Digest) to controllers for or specific route

Options :

  • :type : Authentication type (:basic or :digest) - default : :basic
  • :realm : realm ;) - default : "Capcode.app"
  • :opaque : Your secret passphrase. You MUST set it if you use Digest Auth - default : "opaque"
  • :routes : Routes - default : "/"

The block must return a Hash of username => password like that :

  {
    "user1" => "pass1",
    "user2" => "pass2",
    # ...
  }

[Source]

     # File lib/capcode.rb, line 579
579:     def http_authentication( opts = {}, &b )
580:       options = {
581:         :type => :basic,
582:         :realm => "Capcode.app",
583:         :opaque => "opaque",
584:         :routes => "/"
585:       }.merge( opts )
586:       
587:       options[:autz] = b.call()
588:       
589:       @__auth__ ||= {}
590:       
591:       if options[:routes].class == Array
592:         options[:routes].each do |r|
593:           @__auth__[r] = options
594:         end
595:       else
596:         @__auth__[options[:routes]] = options
597:       end      
598:     end

[Source]

     # File lib/capcode.rb, line 829
829:     def logger
830:       @cclogger
831:     end

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

  Capcode.map( "/file" ) do
    Rack::File.new( "." )
  end

[Source]

     # File lib/capcode.rb, line 544
544:     def map( route, &b )
545:       Capcode.routes[route] = yield
546:     end

Hash containing all the request parameters (GET or POST)

[Source]

     # File lib/capcode.rb, line 401
401:         def params
402:           @request.params
403:         end

Return the Rack::Request object

[Source]

     # File lib/capcode.rb, line 416
416:         def request
417:           @request
418:         end

Return the Rack::Response object

[Source]

     # File lib/capcode.rb, line 421
421:         def response
422:           @response
423:         end

Start your application.

Options : see Capcode::Configuration.set

Options set here replace the ones set globally

[Source]

     # File lib/capcode.rb, line 689
689:     def run( args = {} )
690:       Capcode::Configuration.configuration(args)
691:       
692:       # Parse options
693:       opts = OptionParser.new do |opts|
694:         opts.banner = "Usage: #{File.basename($0)} [options]"
695:         opts.separator ""
696:         opts.separator "Specific options:"
697: 
698:         opts.on( "-C", "--console", "Run in console mode with IRB (default: false)" ) { 
699:           Capcode::Configuration.set :console, true
700:         }
701:         opts.on( "-h", "--host HOSTNAME", "Host for web server to bind to (default: #{Capcode::Configuration.get(:host)})" ) { |h|
702:           Capcode::Configuration.set :host, h
703:         }
704:         opts.on( "-p", "--port NUM", "Port for web server (default: #{Capcode::Configuration.get(:port)})" ) { |p|
705:           Capcode::Configuration.set :port, p
706:         }
707:         opts.on( "-d", "--daemonize [true|false]", "Daemonize (default: #{Capcode::Configuration.get(:daemonize)})" ) { |d|
708:           Capcode::Configuration.set :daemonize, d
709:         }
710:         opts.on( "-r", "--root PATH", "Working directory (default: #{Capcode::Configuration.get(:root)})" ) { |w|
711:           Capcode::Configuration.set :root, w
712:         }
713:         opts.on( "-s", "--static PATH", "Static directory -- relative to the root directory (default: #{Capcode::Configuration.get(:static)})" ) { |r|
714:           Capcode::Configuration.set :static, r
715:         }
716:         opts.on( "-S", "--server SERVER", "Server to use (default: #{Capcode::Configuration.get(:server)})" ) { |r|
717:           Capcode::Configuration.set :server, r
718:         }
719: 
720:         opts.separator ""
721:         opts.separator "Common options:"
722: 
723:         opts.on("-?", "--help", "Show this message") do
724:           puts opts
725:           exit
726:         end  
727:         opts.on("-v", "--version", "Show versions") do
728:           puts "Capcode version #{Capcode::CAPCOD_VERION} (ruby v#{RUBY_VERSION})"
729:           exit
730:         end  
731:         opts.on_tail( "-V", "--verbose", "Run in verbose mode" ) do
732:           Capcode::Configuration.set :verbose, true
733:         end
734:       end
735:       
736:       begin
737:         opts.parse! ARGV
738:       rescue OptionParser::ParseError => ex
739:         puts "!! #{ex.message}"
740:         puts "** use `#{File.basename($0)} --help` for more details..."
741:         exit 1
742:       end
743:       
744:       # Run in the Working directory
745:       puts "** Go on root directory (#{File.expand_path(Capcode::Configuration.get(:root))})" if Capcode::Configuration.get(:verbose)
746:       Dir.chdir( Capcode::Configuration.get(:root) ) do
747:         
748:         # Check that mongrel exists 
749:         if Capcode::Configuration.get(:server).nil? || Capcode::Configuration.get(:server) == "mongrel"
750:           begin
751:             require 'mongrel'
752:             Capcode::Configuration.set :server, :mongrel
753:           rescue LoadError 
754:             puts "!! could not load mongrel. Falling back to webrick."
755:             Capcode::Configuration.set :server, :webrick
756:           end
757:         end
758:         
759:         # From rackup !!!
760:         if Capcode::Configuration.get(:daemonize)
761:           if /java/.match(RUBY_PLATFORM).nil?
762:             if RUBY_VERSION < "1.9"
763:               exit if fork
764:               Process.setsid
765:               exit if fork
766:               # Dir.chdir "/"
767:               File.umask 0000
768:               STDIN.reopen "/dev/null"
769:               STDOUT.reopen "/dev/null", "a"
770:               STDERR.reopen "/dev/null", "a"
771:             else
772:               Process.daemon
773:             end
774:           else
775:             puts "!! daemonize option unavailable on #{RUBY_PLATFORM} platform."
776:           end
777:         
778:           File.open(Capcode::Configuration.get(:pid), 'w'){ |f| f.write("#{Process.pid}") }
779:           at_exit { File.delete(Capcode::Configuration.get(:pid)) if File.exist?(Capcode::Configuration.get(:pid)) }
780:         end
781:         
782:         app = nil
783:         if block_given?
784:           app = application(Capcode::Configuration.get) { yield( self ) }
785:         else
786:           app = application(Capcode::Configuration.get)
787:         end
788:         
789:         if Capcode::Configuration.get(:console)
790:           puts "Run console..."
791:           IRB.start
792:           exit
793:         end
794:         
795:         # Start server
796:         case Capcode::Configuration.get(:server).to_s
797:         when "mongrel"
798:           puts "** Starting Mongrel on #{Capcode::Configuration.get(:host)}:#{Capcode::Configuration.get(:port)}"
799:           Rack::Handler::Mongrel.run( app, {:Port => Capcode::Configuration.get(:port), :Host => Capcode::Configuration.get(:host)} ) { |server|
800:             trap "SIGINT", proc { server.stop }
801:           }
802:         when "webrick"
803:           puts "** Starting WEBrick on #{Capcode::Configuration.get(:host)}:#{Capcode::Configuration.get(:port)}"
804:           Rack::Handler::WEBrick.run( app, {:Port => Capcode::Configuration.get(:port), :BindAddress => Capcode::Configuration.get(:host)} ) { |server|
805:             trap "SIGINT", proc { server.shutdown }
806:           }
807:         when "thin"
808:           puts "** Starting Thin on #{Capcode::Configuration.get(:host)}:#{Capcode::Configuration.get(:port)}"
809:           Rack::Handler::Thin.run( app, {:Port => Capcode::Configuration.get(:port), :Host => Capcode::Configuration.get(:host)} ) { |server|
810:             trap "SIGINT", proc { server.stop }
811:           }
812:         when "unicorn"
813:           require 'unicorn/launcher'
814:           puts "** Starting Unicorn on #{Capcode::Configuration.get(:host)}:#{Capcode::Configuration.get(:port)}"
815:           Unicorn.run( app, {:listeners => ["#{Capcode::Configuration.get(:host)}:#{Capcode::Configuration.get(:port)}"]} )
816:         when "rainbows"
817:           require 'unicorn/launcher'
818:           require 'rainbows'
819:           puts "** Starting Rainbow on #{Capcode::Configuration.get(:host)}:#{Capcode::Configuration.get(:port)}"
820:           Rainbows.run( app, {:listeners => ["#{Capcode::Configuration.get(:host)}:#{Capcode::Configuration.get(:port)}"]} )
821:         end
822:       end
823:     end

Session hash

[Source]

     # File lib/capcode.rb, line 411
411:         def session
412:           @env['rack.session']
413:         end

[Source]

   # File lib/capcode/configuration.rb, line 3
3:     def set(key, value, opts = {}); Configuration.set(key, value, opts); end

This method allow you to use a Rack middleware

Example :

  module Capcode
    ...
    use Rack::Codehighlighter, :coderay, :element => "pre",
      :pattern => /\A:::(\w+)\s*\n/, :logging => false
    ...
  end

[Source]

     # File lib/capcode.rb, line 558
558:     def use(middleware, *args, &block)
559:       middlewares << [middleware, args, block]
560:     end

[Validate]