# 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 152
152:     def Route *u
153:       Class.new {
154:         meta_def(:__urls__){
155:           # < Route '/hello/world/([^\/]*)/id(\d*)', '/hello/(.*)'
156:           # # => [ {'/hello/world' => '([^\/]*)/id(\d*)', '/hello' => '(.*)'}, 2, <Capcode::Klass> ]
157:           h = {}
158:           max = 0
159:           u.each do |_u|
160:             m = /\/([^\/]*\(.*)/.match( _u )
161:             if m.nil?
162:               raise Capcode::RouteError, "Route `#{_u}' already defined with regexp `#{h[_u]}' !", caller if h.keys.include?(_u)
163:               h[_u] = ''
164:             else
165:               _pre = m.pre_match
166:               _pre = "/" if _pre.size == 0
167:               raise Capcode::RouteError, "Route `#{_pre}' already defined with regexp `#{h[_pre]}' !", caller if h.keys.include?(_pre)
168:               h[_pre] = m.captures[0]
169:               max = Regexp.new(m.captures[0]).number_of_captures if max < Regexp.new(m.captures[0]).number_of_captures
170:             end
171:           end
172:           [h, max, self]
173:         }
174: 
175:         # Hash containing all the request parameters (GET or POST)
176:         def params
177:           @request.params
178:         end
179:         
180:         # Hash containing all the environment variables
181:         def env
182:           @env
183:         end
184:         
185:         # Hash session
186:         def session
187:           @env['rack.session']
188:         end
189:         
190:         # Return the Rack::Request object
191:         def request
192:           @request
193:         end
194:         
195:         # Return the Rack::Response object
196:         def response
197:           @response
198:         end
199:         
200:         def call( e ) #:nodoc:
201:           @env = e
202:           @response = Rack::Response.new
203:           @request = Rack::Request.new(@env)
204: 
205:           r = case @env["REQUEST_METHOD"]
206:             when "GET"
207:               finalPath = nil
208:               finalArgs = nil
209:               finalNArgs = nil
210:               
211:               aPath = @request.path.gsub( /^\//, "" ).split( "/" )
212:               self.class.__urls__[0].each do |p, r|
213:                 xPath = p.gsub( /^\//, "" ).split( "/" )
214:                 if (xPath - aPath).size == 0
215:                   diffArgs = aPath - xPath
216:                   diffNArgs = diffArgs.size
217:                   if finalNArgs.nil? or finalNArgs > diffNArgs
218:                     finalPath = p
219:                     finalNArgs = diffNArgs
220:                     finalArgs = diffArgs
221:                   end
222:                 end
223:                 
224:               end
225: 
226:               nargs = self.class.__urls__[1]
227:               regexp = Regexp.new( self.class.__urls__[0][finalPath] )
228:               
229:               args = regexp.match( Rack::Utils.unescape(@request.path).gsub( Regexp.new( "^#{finalPath}" ), "" ).gsub( /^\//, "" ) )
230:               if args.nil?
231:                 raise Capcode::ParameterError, "Path info `#{@request.path_info}' does not match route regexp `#{regexp.source}'"
232:               else
233:                 args = args.captures
234:               end
235:               
236:               while args.size < nargs
237:                 args << nil
238:               end
239:                                           
240:               get( *args )
241:             when "POST"
242:               post
243:           end
244:           if r.respond_to?(:to_ary)
245:             @response.status = r[0]
246:             r[1].each do |k,v|
247:               @response[k] = v
248:             end
249:             @response.body = r[2]
250:           else
251:             @response.write r
252:           end
253:           
254:           @response.finish
255:         end
256:                 
257:         include Capcode::Helpers
258:         include Capcode::Views
259:       }      
260:     end

Public Class method: env()

Hash containing all the environment variables

     # File lib/capcode.rb, line 181
181:         def env
182:           @env
183:         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 267
267:     def map( r, &b )
268:       @@__ROUTES[r] = yield
269:     end

Public Class method: params()

Hash containing all the request parameters (GET or POST)

     # File lib/capcode.rb, line 176
176:         def params
177:           @request.params
178:         end

Public Class method: request()

Return the Rack::Request object

     # File lib/capcode.rb, line 191
191:         def request
192:           @request
193:         end

Public Class method: response()

Return the Rack::Response object

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

Public Class method: session()

Hash session

     # File lib/capcode.rb, line 186
186:         def session
187:           @env['rack.session']
188:         end