Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
e / lib / e-builder / helpers.rb
Size: Mime:
class EBuilder

  # displays URLs the app will respond to,
  # with controller and action that serving each URL.
  def url_map
    mount_controllers!
    sort_routes!
    URLMapPrinter.new(@routes)
  end
  alias urlmap url_map

  unless defined?(EBuilder::URLMapPrinter)
    class URLMapPrinter

      def initialize routes
        @routes = routes.freeze
      end

      def to_s
        out = ''
        @routes.each_pair do |unit,routes|
          routes.each_pair do |route,setup|
            out << "%s\n" % route.source
            setup.each_pair do |rm,rs|
              out << "  %s%s" % [rm, ' ' * (10 - rm.to_s.size)]
              out << "%s\n" % caller(unit, rs)
            end
            out << "\n"
          end
        end
        out
      end

      def inspect
        @routes
      end

      private
      def caller unit, setup
        return setup[:app] if [:rewriter, :application].include?(unit)
        [setup[:app], setup[:action]].join('#')
      end
    end
  end

  private

  # matching regexp is built to match the action boundary
  # and whatever that comes after boundary.
  # this method will simply concatenate boundary with whatever else.
  def matched_path_info matches
    matches[1].to_s + matches[2].to_s # 2x faster than matches[1..2].join
  end

  # routes should be sorted by length in descending order,
  # that's it, longer routes goes first as they are more relevant.
  def sort_routes!
    sorted_routes = {}
    @routes.each_pair do |unit,routes|
      sorted_routes[unit] = Hash[routes.sort do |a,b|
        route_priority(*b) <=> route_priority(*a)
      end]
    end
    @routes = sorted_routes
  end

  def route_priority route, setup
    if priority = setup.values.first[:priority]
      return priority
    end
    route.is_a?(Regexp) ? route.source.length : route.to_s.length
  end

  # splitting path_info into format and path,
  # so "index.html" returns [".html", "index"]
  # - "index/something.html" => [".html", "index/something"]
  # - "index" => [nil, "index"]
  # - "index/something" => [nil, "index/something"]
  #
  # if ".html" is a unrecognized format
  # the path remains the same and a nil format returned
  def handle_format formats, path_info
    format = nil
    if formats.any?
      if format = formats[path_info]
        path_info = ''
      elsif format = formats[File.extname(path_info)]
        # File join + dirname + basename
        # is faster than building a regexp and sub path info based on it
        path_info = File.join File.dirname(path_info), File.basename(path_info, format)
      end
    end
    [format, path_info]
  end

  def valid_context? unit, setup, env
    if unit == :rewriter # rewriter works only on GET and HEAD requests
      return valid_rewriter_context?(setup, env[ENV__REQUEST_METHOD])
    end
    valid_route_context?(setup, env[ENV__REQUEST_METHOD])
  end

  # check whether action respond to given request method
  # or to whatever method.
  # RESTless actions like `def index`, `def edit` will respond to whatever method.
  # RESTified actions, like `def post_index`, `def put_edit`
  # will respond only to specified request method.
  def valid_route_context? route_setup, request_method
    route_setup[request_method] || route_setup[:*]
  end

  # check whether it is a GET or HEAD request
  # cause rewriters are listening only on these request methods.
  # if yes, extract rewriter setup using GET key,
  # cause rewriters are added like {'GET' => {app: logic_proc}}
  def valid_rewriter_context? overall_setup, request_method
    (request_method == HTTP__DEFAULT_REQUEST_METHOD ||
      request_method == HTTP__HEAD_REQUEST_METHOD)  &&
      overall_setup[HTTP__DEFAULT_REQUEST_METHOD]
  end

  def valid_host? accepted_hosts, env
    return true if accepted_hosts.empty?
    http_host, server_name, server_port =
      env.values_at(ENV__HTTP_HOST, ENV__SERVER_NAME, ENV__SERVER_PORT)
    accepted_hosts[http_host] ||
      accepted_hosts[server_name] ||
      http_host == server_name ||
      http_host == server_name+':'+server_port # 3x faster than create and join an array
  end

  def normalize_path path
    (path_ok?(path) ? path : '/' << path).freeze
  end

  # checking whether path is empty or starts with a slash
  def path_ok? path
    # comparing fixnums are much faster than comparing strings
    path.hash == (@empty_string_hash ||= '' .hash) || # faster than path.empty?
      path[0].hash == (@slash_hash   ||= '/'.hash)    # faster than path =~ /^\//
  end

  def not_found env
    [
      STATUS__NOT_FOUND,
      {HEADER__CONTENT_TYPE => CONTENT_TYPE__PLAIN},
      ['Not Found: %s' % env[ENV__PATH_INFO]]
    ]
  end

  def not_implemented implemented
    [
      STATUS__NOT_IMPLEMENTED,
      {HEADER__CONTENT_TYPE => CONTENT_TYPE__PLAIN},
      ['Resource found but it can be accessed only through %s' % implemented]
    ]
  end

end