Parent

Class Index [+]

Quicksearch

Synfeld::App

See the synopsis section of README.rdoc for usage.

See the README.rdoc for an overview of an Synfeld::App, and see the Rack::Mount project for more information on Rack::Mount style routing.

Variables of note:

  @response
     a hash with keys :body, :headers, :status_code, the 3 items all rack handlers are expected to set.
     Body is a string, status code is an http status code integer, and headers is a hash that
     should conform to rack's contract.

  @env
     The rack env passed into this apps #call method

  @params
     The params as determined by the matching Rack::Mount route.

  @root_dir
     This dir is prepended to relative paths to locate files.

  @logger
     Either you pass in the @logger that synfeld uses, or it sets one up on STDOUT.

Attributes

env[RW]

(Not documented)

logger[RW]

(Not documented)

params[RW]

(Not documented)

response[RW]

(Not documented)

root_dir[RW]

(Not documented)

Public Class Methods

new(opts = {}) click to toggle source

Options:

  :logger => where to log to.
             Note this is not the same thing as the rack access log (although you
             can pass that logger in if you want). Default: Logger.new(STDOUT)
# File lib/synfeld/base.rb, line 35
    def initialize(opts = {})

      @logger = opts[:logger]
      if self.logger.nil?
        @logger = Logger.new(STDOUT)
        puts "WARNING: Synfeld not configured with a logger, using STDOUT. Won't have much to say if running as a daemon."
      end

      @root_dir = opts[:root_dir] 
      if self.root_dir.nil?
        raise "You have to pass in the location of the 'root_dir', where all the files in your synfeld app are located" 
      end

      Kernel.at_exit {self.whine("Alright, I'm outta here.")}
    end

Public Instance Methods

action() click to toggle source

The name of the action method bound to the route that mathed the incoming request.

# File lib/synfeld/base.rb, line 106
    def action
      self.params[:action]
    end
add_route(string_or_regex, opts = {}) click to toggle source

See the README for a full explanation of how to use this method.

# File lib/synfeld/base.rb, line 81
    def add_route(string_or_regex, opts = {})
      raise "You have to provide an :action method to call" unless opts[:action]
      method = (opts.delete(:method) || 'GET').to_s.upcase
      # Adapt string_or_regex into a rack-mount regex route. If it is a string, convert it to a
      # rack-mount compatable regex. In paths that look like /some/:var/in/path, convert the ':var'
      # bits to rack-mount variables.
      if string_or_regex.is_a?(String)
        regex_string = "^" + string_or_regex.gsub(/:(([^\/]+))/){|s| "(?#{@@__regex_colon}<#{$1}>.*)" } + "$"
        regex = %r{#{regex_string}}
        #puts regex_string # dbg
      else
        regex = string_or_regex
      end

      # Add the route to rack-mount
      @set.add_route(self,
                    {:path_info => regex, :request_method => method.upcase},
                    opts)
    end
as_rack_app() click to toggle source

Return self as a rackup-able rack application.

# File lib/synfeld/base.rb, line 56
    def as_rack_app
      routes = Rack::Mount::RouteSet.new_without_optimizations do |set|
        @set = set
        self.add_routes
        add_route %r{^.*$},  :action => "render_static" 
      end
      app = Rack::Builder.new {
        #use Rack::CommonLogger, $stderr
        #use Rack::Reloader, 0
        run routes
      }.to_app
    end
call(env) click to toggle source

The rack call method

# File lib/synfeld/base.rb, line 70
    def call(env)
      dup._call(env) # be thread-safe
    end

Protected Instance Methods

content_type!(ext) click to toggle source

Given a file extention, determine the ‘Content-Type’ and then set the @response[:headers][‘Content-Type’]. Unrecognized extentions are set to content type of ‘text/plain’.

# File lib/synfeld/base.rb, line 245
      def content_type!(ext)
        case ext.downcase
        when 'haml'; t = 'text/html'
        when 'erb'; t = 'text/html'
# I believe all the rest are determined accurately by the Rack::Mime.mime_type call in the else clause below.
#        when 'html'; t = 'text/html'
#        when 'js'; t = 'text/javascript'
#        when 'css'; t = 'text/css'
#        when 'png'; t = 'image/png'
#        when 'gif'; t = 'image/gif'
#        when 'jpg'; t = 'image/jpeg'
#        when 'jpeg'; t = 'image/jpeg'
        else t = Rack::Mime.mime_type('.' + ext, 'text/plain')
        end
        #puts("----#{ext}:" + t.inspect) # dbg
        (self.response[:headers]['Content-Type'] = t) if t
      end
full_path(fn) click to toggle source

Return fn if a file by that name exists. If not, concatenate the @root_dir with the fn, and return that if it exists. Raise if the actual file cannot be determined.

NOTE: no effort is made to protect access to files outside of your application’s root dir. If you permit filepaths as request parameters, then it is up to you to make sure that they do not point to some sensitive part of your file-system.

# File lib/synfeld/base.rb, line 269
      def full_path(fn)
        if F.exist?(fn)
          return fn
        elsif F.exist?(full_fn = F.join(self.root_dir, fn))
          return full_fn
        else
          raise "Could not find file '#{fn}' (full path '#{full_fn}')" 
        end
      end
no_action() click to toggle source

Overrideable method that handles a missing action that was defined by a route

# File lib/synfeld/base.rb, line 163
      def no_action
        self.response[:body] = "Action '#{self.action}' not found in '#{self.class}'"
        self.response[:status_code] = 500
      end
no_route() click to toggle source

Overrideable method that handles 404

# File lib/synfeld/base.rb, line 169
      def no_route
          self.response[:body] = "route not found for: '#{self.env['REQUEST_URI']}'"
          self.response[:status_code] = 404
      end
render_erb(fn, locals = {}) click to toggle source

Render an erb file. ‘fn’ is a full path, or a path relative to @root_dir. ‘locals’ is a hash definining variables to be passed to the template.

# File lib/synfeld/base.rb, line 207
      def render_erb(fn, locals = {})

        if not defined? Erb
          begin
            require 'erb'
          rescue LoadError => x
            return self.whine("Erb is not installed, required in order to render '#{fn}'")
          end
        end

        template = ERB.new F.read(full_path(fn))

        bind = binding
        locals.each do |n,v| 
          raise "Locals must be symbols. Not a symbol: #{n.inspect}" unless n.is_a?(Symbol) 
          eval("#{n} = locals[:#{n}]", bind)
        end
        template.result(bind)
      end
render_haml(fn, locals = {}) click to toggle source

Render a haml file. ‘fn’ is a full path, or a path relative to @root_dir. ‘locals’ is a hash definining variables to be passed to the template.

# File lib/synfeld/base.rb, line 192
      def render_haml(fn, locals = {})

        if not defined? Haml
          begin
            require 'haml'
          rescue LoadError => x
            return self.whine("Haml is not installed, required in order to render '#{fn}'")
          end
        end

        Haml::Engine.new(F.read(full_path(fn)) ).render(Object.new, locals)
      end
render_html(fn) click to toggle source

Render an html file. ‘fn’ is a full path, or a path relative to @root_dir.

# File lib/synfeld/base.rb, line 179
      def render_html(fn)
        F.read(full_path(fn))
      end
render_json(json) click to toggle source

Serve up a blob of json (just sets Content-Type to ‘text/javascript’ and sets the body to the json passed in to this method).

# File lib/synfeld/base.rb, line 185
      def render_json(json)
        self.response[:headers]['Content-Type'] = 'text/javascript'
        self.response[:body] = json
      end
render_static() click to toggle source

(Not documented)

# File lib/synfeld/base.rb, line 227
      def render_static
        fn = F.expand_path(F.join(root_dir, self.env['REQUEST_URI']))
        #puts fn # dbg
        if F.exist?(fn) and not F.directory?(fn)
          self.content_type!(fn.split('.').last)
          F.read(fn)
        else
          return self.no_route
        end
      end
whine(msg) click to toggle source

send an error message to the log prepended by “Synfeld: “

# File lib/synfeld/base.rb, line 156
      def whine msg
        logger.error("Synfeld laments: " + msg)
        return msg
      end

Disabled; run with $DEBUG to generate this.

[Validate]

Generated with the Darkfish Rdoc Generator 1.1.6.