# Module: Capcode
[ "README", "AUTHORS", "COPYING", "lib/capcode.rb", nil].each do
Capcode.view_html
Capcode::Helpers.view_html
Capcode::HTTPError.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 130
130:     def Route *u
131:       Class.new {
132:         meta_def(:__urls__){
133:           # < Route '/hello/world/([^\/]*)/id(\d*)', '/hello/(.*)'
134:           # # => [ {'/hello/world' => '([^\/]*)/id(\d*)', '/hello' => '(.*)'}, 2, <Capcode::Klass> ]
135:           h = {}
136:           max = 0
137:           u.each do |_u|
138:             m = /\/([^\/]*\(.*)/.match( _u )
139:             if m.nil?
140:               raise Capcode::RouteError, "Route `#{_u}' already defined with regexp `#{h[_u]}' !", caller if h.keys.include?(_u)
141:               h[_u] = ''
142:             else
143:               _pre = m.pre_match
144:               _pre = "/" if _pre.size == 0
145:               raise Capcode::RouteError, "Route `#{_pre}' already defined with regexp `#{h[_pre]}' !", caller if h.keys.include?(_pre)
146:               h[_pre] = m.captures[0]
147:               max = Regexp.new(m.captures[0]).number_of_captures if max < Regexp.new(m.captures[0]).number_of_captures
148:             end
149:           end
150:           [h, max, self]
151:         }
152: 
153:         # Hash containing all the request parameters (GET or POST)
154:         def params
155:           @request.params
156:         end
157:         
158:         # Hash containing all the environment variables
159:         def env
160:           @env
161:         end
162:         
163:         # Hash session
164:         def session
165:           @env['rack.session']
166:         end
167:         
168:         # Return the Rack::Request object
169:         def request
170:           @request
171:         end
172:         
173:         # Return the Rack::Response object
174:         def response
175:           @response
176:         end
177:         
178:         def call( e ) #:nodoc:
179:           @env = e
180:           @response = Rack::Response.new
181:           @request = Rack::Request.new(@env)
182: 
183:           r = case @env["REQUEST_METHOD"]
184:             when "GET"
185:               finalPath = nil
186:               finalArgs = nil
187:               finalNArgs = nil
188:               
189:               aPath = @request.path.gsub( /^\//, "" ).split( "/" )
190:               self.class.__urls__[0].each do |p, r|
191:                 xPath = p.gsub( /^\//, "" ).split( "/" )
192:                 if (xPath - aPath).size == 0
193:                   diffArgs = aPath - xPath
194:                   diffNArgs = diffArgs.size
195:                   if finalNArgs.nil? or finalNArgs > diffNArgs
196:                     finalPath = p
197:                     finalNArgs = diffNArgs
198:                     finalArgs = diffArgs
199:                   end
200:                 end
201:                 
202:               end
203: 
204: # TODO : correct above to use this :
205: #puts "finalPath = #{finalPath}"
206: #puts "finalNArgs = #{finalNArgs}"
207: #print "finalArgs = "; p finalArgs
208: 
209:               nargs = self.class.__urls__[1]
210:               regexp = Regexp.new( self.class.__urls__[0][finalPath] )
211:               
212:               args = regexp.match( Rack::Utils.unescape(@request.path_info).gsub( /^\//, "" ) )
213:               if args.nil?
214:                 raise Capcode::ParameterError, "Path info `#{@request.path_info}' does not match route regexp `#{regexp.source}'"
215:               else
216:                 args = args.captures
217:               end
218:               
219:               while args.size < nargs
220:                 args << nil
221:               end
222:                                           
223:               get( *args )
224:             when "POST"
225:               post
226:           end
227:           if r.respond_to?(:to_ary)
228:             @response.status = r[0]
229:             r[1].each do |k,v|
230:               @response[k] = v
231:             end
232:             @response.body = r[2]
233:           else
234:             @response.write r
235:           end
236:           
237:           @response.finish
238:         end
239:                 
240:         include Capcode::Helpers
241:       }      
242:     end

Public Class method: env()

Hash containing all the environment variables

     # File lib/capcode.rb, line 159
159:         def env
160:           @env
161:         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 249
249:     def map( r, &b )
250:       @@__ROUTES[r] = yield
251:     end

Public Class method: params()

Hash containing all the request parameters (GET or POST)

     # File lib/capcode.rb, line 154
154:         def params
155:           @request.params
156:         end

Public Class method: request()

Return the Rack::Request object

     # File lib/capcode.rb, line 169
169:         def request
170:           @request
171:         end

Public Class method: response()

Return the Rack::Response object

     # File lib/capcode.rb, line 174
174:         def response
175:           @response
176:         end

Public Class method: run( args = {} )

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)
     # File lib/capcode.rb, line 263
263:     def run( args = {} )
264:       conf = {
265:         :port => args[:port]||3000, 
266:         :host => args[:host]||"localhost",
267:         :server => args[:server]||nil,
268:         :log => args[:log]||$stdout,
269:         :session => args[:session]||{},
270:         :pid => args[:pid]||"#{$0}.pid",
271:         :daemonize => args[:daemonize]||false,
272:         :db_config => args[:db_config]||"database.yml"
273:       }
274:       
275:       # Check that mongrel exists 
276:       if conf[:server].nil? || conf[:server] == "mongrel"
277:         begin
278:           require 'mongrel'
279:           conf[:server] = "mongrel"
280:         rescue LoadError 
281:           puts "!! could not load mongrel. Falling back to webrick."
282:           conf[:server] = "webrick"
283:         end
284:       end
285:           
286:       Capcode.constants.each do |k|
287:         begin
288:           if eval "Capcode::#{k}.public_methods(true).include?( '__urls__' )"
289:             u, m, c = eval "Capcode::#{k}.__urls__"
290:             u.keys.each do |_u|
291:               raise Capcode::RouteError, "Route `#{_u}' already define !", caller if @@__ROUTES.keys.include?(_u)
292:               @@__ROUTES[_u] = c.new
293:             end
294:           end
295:         rescue => e
296:           raise e.message
297:         end
298:       end
299:       
300:       app = Rack::URLMap.new(@@__ROUTES)
301:       app = Rack::Session::Cookie.new( app, conf[:session] )
302:       app = Capcode::HTTPError.new(app)
303:       app = Rack::ContentLength.new(app)
304:       app = Rack::Lint.new(app)
305:       app = Rack::ShowExceptions.new(app)
306: #      app = Rack::Reloader.new(app) ## -- NE RELOAD QUE capcode.rb -- So !!!
307:       app = Rack::CommonLogger.new( app, Logger.new(conf[:log]) )
308:       
309:       # From rackup !!!
310:       if conf[:daemonize]
311:         if RUBY_VERSION < "1.9"
312:           exit if fork
313:           Process.setsid
314:           exit if fork
315:           # Dir.chdir "/"
316:           File.umask 0000
317:           STDIN.reopen "/dev/null"
318:           STDOUT.reopen "/dev/null", "a"
319:           STDERR.reopen "/dev/null", "a"
320:         else
321:           Process.daemon
322:         end
323: 
324:         File.open(conf[:pid], 'w'){ |f| f.write("#{Process.pid}") }
325:         at_exit { File.delete(conf[:pid]) if File.exist?(conf[:pid]) }
326:       end
327:       
328:       # Start database
329:       if self.methods.include? "db_connect"
330:         db_connect( conf[:db_config], conf[:log] )
331:       end
332:       
333:       # Start server
334:       case conf[:server]
335:       when "mongrel"
336:         puts "** Starting Mongrel on #{conf[:host]}:#{conf[:port]}"
337:         Rack::Handler::Mongrel.run( app, {:Port => conf[:port], :Host => conf[:host]} ) { |server|
338:           trap "SIGINT", proc { server.stop }
339:         }
340:       when "webrick"
341:         puts "** Starting WEBrick on #{conf[:host]}:#{conf[:port]}"
342:         Rack::Handler::WEBrick.run( app, {:Port => conf[:port], :BindAddress => conf[:host]} ) { |server|
343:           trap "SIGINT", proc { server.shutdown }
344:         }
345:       end
346:     end

Public Class method: session()

Hash session

     # File lib/capcode.rb, line 164
164:         def session
165:           @env['rack.session']
166:         end